I am trying to create something like Facebook NewsFeed where, I am using custom UICollectionViewCell to display data (Text/Image) from JSON. I have 2 different APIs. One for text and another for images(Every cell doesn’t have image).
So, First of all I am getting all text values in to my cells from my textAPI and reloading myCollectionView. That works perfect.
Now for the Images, I am using ImageFetcher to fetch images,
func ImageFetcher(postId : NSNumber, completion : ((_ image: UIImage?) -> Void)!) {
var image = UIImage()
let urlString = "http://myImageAPI/Image/(postId)"
let jsonUrlString = URL(string: urlString)
print(urlString)
URLSession.shared.dataTask(with: jsonUrlString!) { (data, response, error) in
do {
if let jsonData = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String:Any] {
if let images = jsonData["Image"] as? String {
if images == "" {
print("No Image")
} else {
let dataDecoded : Data? = Data(base64Encoded: images, options: .ignoreUnknownCharacters)
image = UIImage(data: dataDecoded!)!
completion(image)
}
}
}
else {
completion(nil)
}
} catch {
print(error.localizedDescription)
}
}.resume()
}
To display image in to Cell,
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// Displaying other elements with text
DispatchQueue.main.async {
self.ImageFetcher(postId: self.myArray[indexPath.item].id!, completion: { (image) -> Void in
customCell.mainImage.image = image
})
// Declared "indexPaths" var indexPaths = [IndexPath]()
// Added this lines
// let indexPath = IndexPath(item: indexPath.item, section: 0)
// self.indexPaths.append(indexPath)
}
return customCell
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.jsonParsing()
}
func jsonParsing() {
//Fetching text data from textAPI
//DispatchQueue.main.async {
// self.collectionView.reloadItems(at: self.indexPaths)
//}
}
Code works without any error but the issue is Images only appears when I click on them. (I can see empty/white imageView in a cell until I click it. As soon as I click on imageView the Image appears) I feel its something with DispatchQueue.main.async but, not sure.
I do not want to reload the whole collectionView after fetching the images. Just want to reload those cells which have Image. I found
collectionView.reloadItemsAtIndexPaths(myArrayOfIndexPaths)
on many solution but don’t know how to make it work in this scenario. Can anyone please help me here? Any help will be much appreciated.
2
Answers
Can you try this?
instead of
===================== Updated ======================
I ended up helping Snehal not only image load problem but also a couple of other issues with collection view and image caches. I suggested him to use a third party library like SDWebImage but found out his api returns image as base64 string in the response. So I just go ahead and clean up his code and write the code that I think it’s a good string point that might help him.
Better way to do this is like make a model that class that contains url of images and your text variables like
class AnyName {
var url: String?
var desc: String?
Now in your viewcontroller make array of above class name
var items = AnyName
Now by first api hitting you can set values for text in this array and passed to collectionview and load cells with text and thereafter you can change arrayvalues for url and reload collectionview easily