I have a collection view in a view controller.. There is one problem which i can't figure out. The custom cell in a collection view is displaying one item from an array.
Cant figure out what is missing in the code.. I have used both the delegate and data source method..
Here is the code i am using..
viewDidLoad()
pathRef.observeSingleEventOfType(.ChildAdded, withBlock: { (snapshot) in
let post = CollectionStruct(key: snapshot.key, snapshot: snapshot.value as! Dictionary<String, AnyObject>)
self.userCollection.append(post)
let indexPath = NSIndexPath(forItem: self.userCollection.count-1, inSection: 0)
self.collectionView!.insertItemsAtIndexPaths([indexPath])
})
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return userCollection.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionCell", forIndexPath: indexPath) as! CollectionViewCell
let post = userCollection[indexPath.row]
if let imageUrl = post.category{
if imageUrl.hasPrefix("gs://"){
FIRStorage.storage().referenceForURL(imageUrl).dataWithMaxSize(INT64_MAX, completion: { (data, error) in
if let error = error {
print("Error Loading")
}
cell.userImg.image = UIImage.init(data: data!)
})
}else if let url = NSURL(string: imageUrl), data = NSData(contentsOfURL: url){
cell.userImg.image = UIImage.init(data: data)
}
}
return cell
}
I am trying to retrieve images stored in firebase database..
Use observeEventType instead of observeSingleEventOfType. More info in the docs.
Related
My question is simple but I couldn't find a solution. When I get JSON data from server I want to display the data to collectionviewcell but I got index out of range error.
This is my code:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SiparislerTumAnasayfa", for: indexPath) as! SiparislerTumAnasayfa
let url = URL(string: "https://abc/api/SiparislerTumListeler/abc")
let session = URLSession.shared
let task = session.dataTask(with: url!) { (data, response, error) in
if error != nil {
print(error)
}
else
{
if data != nil{
do{
let responseJSON = try? JSONSerialization.jsonObject(with: data!, options: [])
if let responseJSON = responseJSON as? [String: Any] {
self.jsonArray = responseJSON["results"] as? [[String: Any]]
DispatchQueue.main.async {
let row = self.jsonArray![indexPath.row]
if let urunAdi = row["siparis_urun_adi"] as? String {
cell.siparisUrunAdi.text = urunAdi
}
}
}
}
catch {
print(error)
}
}
}
}
task.resume()
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.jsonArray!.count
}
[indexPath.row] is where I got the error.
You need to add code that handles the case where indexPath.row is greater or equal to self.jsonArray.count.
Maybe the number of array from response api are less than the numberOfItemsInSection
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {....}
I tested the collection view can displayed the content. However, I can't retrieve and add array result in the collection view.
Here is my code:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! MainPageCollectionViewCell
cell.FoodTitle.text = arr[indexPath.row].title
cell.Food.image = arr[indexPath.row].image_url
return cell
}
About the array, it is a function inside the fetchFoodList.
func fetchFoodList(){
let url = URL(string: "MYAPI.json")
guard let unwrappedUrl = url else { return }
let task = URLSession.shared.dataTask(with: unwrappedUrl, completionHandler: {(data, response, error)in
if error != nil{
print(error!)
} else {
if let urlContent = data{
do {
let json = try JSON(data:data!)
let recipes = json["recipes"]
for arr in recipes.arrayValue{
print(arr["title"])
print(arr["image_url"])
}
}
catch{
print("JSON Processing Failed")
}
}
}
})
task.resume()
}
}
However, the array result title and image_url can displayed in the console.
After appending the array list need to reload collection like this
collectionView.reloadData()
I defined var postImgData = [UIImage]() at beginning of class to store all the images get from sever. The following is the code to get the image from sever
func loadPosts(){
let query = PFQuery(className: "posts")
query.whereKey("username", equalTo:PFUser.current()!.username!)
query.skip = self.picArray.count // skip the already loaded images
query.findObjectsInBackground { (objects, error) in
if error == nil {
if let objects = objects{
for object in objects{
self.collectionView?.performBatchUpdates({
let indexPath = IndexPath(row: self.uuidArray.count, section: 0)
self.uuidArray.append(object.value(forKey: "uuid") as! String)
self.picArray.append(object.value(forKey: "pic") as! PFFile)
self.collectionView?.insertItems(at: [indexPath])
}, completion: nil)
}
}
} else{
print(error!.localizedDescription)
}
}
}
Then i want to use self.postImgData[indexPath.row] = UIImage(data: data!)! to save each image data into postImgData array that defined earlier. But when i run the app it gives error said this line self.postImgData[indexPath.row] = UIImage(data: data!)! Thread 1: Fatal error: Index out of range. I am not sure why its happening? I tried use append function and its working but its didn't show the correct photo when i selected each cell. I am note sure what is correct way to do that? thanks
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return picArray.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//define cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! pictureCell
picArray[indexPath.row].getDataInBackground { (data, error) in
if error == nil {
cell.picImg.image = UIImage(data: data!)
self.postImgData[indexPath.row] = UIImage(data: data!)!
} else {
print(error!.localizedDescription)
}
}
return cell
}
I want to pass the data from my JSON Url to my collection view cell, so after parsing my json I have got array of URL links, the question is how to send it to cell imageView?
here is my code
import UIKit
class ItemsListViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource{
var myItems = [Item]()
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return myItems.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
cell.itemPriseLabel.text = myItems[indexPath.row].currentPrice
let imageUrl = myItems[indexPath.row].productImageUrl
print(imageUrl)
cell.itemImage.image? = imageUrl[indexPath.row]
return cell
}
var category1: Categories?
#IBOutlet weak var colectionViewVariable: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
downloadJSON3 {
self.colectionViewVariable.reloadData()
}
colectionViewVariable?.dataSource = self
colectionViewVariable?.delegate = self
// Do any additional setup after loading the view.
}
}
func getDataFromUrl(url: URL, completion: #escaping (Data?, URLResponse?, Error?) -> ()) {
URLSession.shared.dataTask(with: url) { data, response, error in
completion(data, response, error)
}.resume()
}
func downloadImage(url: URL) {
print("Download Started")
getDataFromUrl(url: url) { data, response, error in
guard let data = data, error == nil else { return }
print(response?.suggestedFilename ?? url.lastPathComponent)
print("Download Finished")
DispatchQueue.main.async() {
self.imageView.image = UIImage(data: data)
}
}
}
Duplicate: Answer found HERE I've stacked it into one concise answer but you should definitely read the answer as it is in the link as it is more complete and better altogether.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
cell.itemPriseLabel.text = myItems[indexPath.row].currentPrice
if let imageUrl = myItems[indexPath.row].productImageUrl.first {
URLSession.shared.dataTask(with: imageUrl, completionHandler: { (data, response, error) in
guard let data = data, response != nil, error == nil else {return}
DispatchQueue.main.async(execute: { () -> Void in
let image = UIImage(data: data)
if let cell = collectionView.cellForItem(at: indexPath) as? CollectionViewCell {
cell.itemImage.image = image
}
})
}).resume()
}
return cell
}
I need some guidance in populating my collection view with images from Firebase. I've searched stack, google and youtube but couldn't find a fix for my problem. The captions (or "description/ requestDescription as I've named them) are displaying correctly, but the images related to each is not. There are 3 unique photos in the Firebase database but only two of them appear in the collection view (all 3 appear when I print the snapshotValue to the console though). Any guidance is greatly appreciated.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return requestDescriptionsArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cellID = "CollectionViewCell"
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath) as! CollectionViewCell
//grab all images from database
ref = FIRDatabase.database().reference()
ref.child("Requests").queryOrdered(byChild: "replies").observe(.childAdded, with: { snapshot in
let snapshotValue = snapshot.value as? NSDictionary
print(snapshotValue!)
//get images
let photoURL = snapshotValue?["photo"] as! String
let url = URL(string: photoURL)
URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
if error != nil {
print(error!)
return
}
DispatchQueue.main.async {
cell.photo.image = UIImage(data: data!)
}
}).resume()
})
cell.requestDescription.text = requestDescriptionsArray[indexPath.item]
return cell
}
func initForImages() {
ref = FIRDatabase.database().reference()
ref.child("Requests").queryOrdered(byChild: "replies").observe(.childAdded, with: { snapshot in
let snapshotValue = snapshot.value as? NSDictionary
print(snapshotValue!)
//get descriptons and add to array
let description = snapshotValue?["Description"] as! String
self.requestDescriptionsArray.insert(description, at: 0)
self.collection.reloadData()
})
}