Reputation: 905
I'm using UICollectionView to show the images in my app.
The problem is that it takes very slow to show images. After 50 seconds, the images in collection view appears. :(
When I find the solution in google, mostly they write the following codes.
But it is not work for me.
cell.layer.shouldRasterize = true
cell.layer.rasterizationScale = UIScreen.main.scale
and
extension SeeAllCollectionView {
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
debugPrint("seeAllLIStCell Count \(assetsTable.count)")
return assetsTable.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "seeAllListCell", for: indexPath) as! SeeAllPhotoCell
let list = assetsTable[(indexPath as NSIndexPath).row]
var imageName: String? = (list.poster_image_url)
var image: UIImage? = (images_cache[imageName!])
if image != nil {
debugPrint("Yes Image")
cell.imageView.image = image
} else{
debugPrint("NO Image")
cell.imageView.image = nil
DispatchQueue.main.async(){
let url = NSURL(string: list.poster_image_url)
let data = NSData(contentsOf:url! as URL)
var image = UIImage(data: data as! Data)
DispatchQueue.main.async(execute: {() -> Void in
cell.movieTitle.text = list.name
cell.imageView?.image = image
})
self.images_cache[imageName!] = image
}
}
return cell
}
}
// MARK: - UICollectionViewDelegate
extension SeeAllCollectionView {
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
debugPrint("Selected")
let list = assetsTable[(indexPath as NSIndexPath).row]
debugPrint(list.poster_image_url)
debugPrint(list.name)
prefs.set(list.poster_image_url, forKey: "poster_image_url")
prefs.set(list.name, forKey: "name")
prefs.set(list.assets_id, forKey: "VIDEO_ID")
prefs.set(false, forKey: "FLAG")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "DetailsChannel") as UIViewController
self.present(vc, animated: true, completion: nil)
}
}
Here is my screenshot when I run the project. I got these many lines of codes when I run.
Please anyone help me how should I do?
Upvotes: 1
Views: 1599
Reputation: 2629
this line:
DispatchQueue.main.async()
upon downloading image is probably causing the error, it blocks the main thread and executes network requests on main (UI) queue, not to mention the fact that these requests are then performed serially (therefore slow). Try to change the snippet to:
DispatchQueue.global.async(qos: DispatchQoS.QoSClass.background){
let url = NSURL(string: list.poster_image_url)
let data = NSData(contentsOf:url! as URL)
var image = UIImage(data: data as! Data)
DispatchQueue.main.async(execute: {() -> Void in
where global
stands for global queue default for such network operations.
EDIT: apart from using main queue for network calls there may be an issue with actually too many images loaded for rows which are not currently visible on the screen. If there are lot of them and connection is not-so-good you will end up with app pending downloads for onscreen cells. Consider lazy loading images only for onscreen cells - and cancelling downloads for rows which are not visible. There is a quite good tutorial (however for table view, but you can easily extend it for collection) in Swift on how to accomplish this.
Upvotes: 0
Reputation: 209
You can give an attempt to SDWebimage All async Thread operations maintained well.
That can provide following advantages
Asynchronously download
Auto Purging Image Cache if memory warnings happen for the app
Image URL caching
Image Caching
Avoid Duplicate Downloads
You can directly use a single method in cell as below
[cell.storeImg sd_setImageWithURL:[NSURL URLWithString:strURL] placeholderImage:kDefaultImageForDisplay];
In your code following line should creates problem as that operation can happen on main thread let data = NSData(contentsOf:url! as URL)
Upvotes: 0
Reputation: 9503
I got the same console error
when I am getting the data from the API call and reload the UITableView
(as per my requirement). My issue is solved by using
DispatchQueue.global(qos: .background).async { // load data in back ground mode so that main thread can be safed.
let url = NSURL(string: list.poster_image_url)
let data = NSData(contentsOf:url! as URL)
var image = UIImage(data: data as! Data)
DispatchQueue.main.async(execute: {
cell.movieTitle.text = list.name
cell.imageView?.image = image
})
self.images_cache[imageName!] = image
}
Screen Shot of Error I got on my Console Before
Upvotes: 1