I cannot figure out why my app's memory ROCKETS up as soon as I begin to scroll the collection view with imageviews populated by SDWebImage. If they are not yet downloaded, then it is fine for a while. But once every image is downloaded, if I even TOUCH the scroll, the app ui becomes unresponsive and the memory rockets so high (over 1GB) that not only does the app crash, the whole OS crashes and restarts.
I have a tableview with a few cells, one of which has a collectionview that I can scroll. I have a data object that I use to populate all the labels and images in collectionViewCell. The cellForItem was very complicated (lots of if statements and switch statements) so I tried moving some of the code out from there and moved it to the didSet method of a property I set up in the collectionViewCell to hold the data object. Then I just set the data object to the property in itemForRow (in background thread) which triggered the didSet method of the individual collectionViewCell to populate the labels and set the image using the sd_set_image method. Here is the relevant code on the tableViewCell:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
print(indexPath.row)
if itemStyle == .Grid {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self.resourceCellIdentifier, for: indexPath) as! ResourceCollectionViewCell
cell.delegate = self
cell.tag = indexPath.row
if self.filter == Filter.Collections || self.resourceArray?[indexPath.row].actionContent == nil {
let resource: ActionContentTemplate?
if self.filter == Filter.Collections {
resource = self.collectionResourceArray?[indexPath.row].actionContentTemplate
} else {
resource = self.resourceArray?[indexPath.row].actionContentTemplate
}
DispatchQueue.global(qos: .userInitiated).async {
cell.dataObject = resource
}
return cell
} else {.....
And this is the didSet method on the CollectionViewCell itself:
var dataObject: ActionContentTemplate? {
didSet {
var cellRow: Int = 0
if self.actionContentTemplate != nil {
....
DispatchQueue.main.async {
cellRow = self.tag
.....
switch self.actionContentTemplate?.contentTypeID?.uintValue {
case ContentTypeVideo.rawValue,
ContentTypeVideoRecording.rawValue,
ContentTypeScreenRecording.rawValue:
.......
case ContentTypeAttachment.rawValue:
let fileType = (self.actionContentTemplate?.contentFileName as NSString?)?.pathExtension.lowercased()
var placeholderImage: UIImage
if fileType == "pdf" {
placeholderImage = UIImage(named: "pdf")!
} else if fileType == "doc" {
placeholderImage = UIImage(named: "doc")!
} else if fileType == "docx" {
placeholderImage = UIImage(named: "doc")!
} else if fileType == "xls" {
placeholderImage = UIImage(named: "xls")!
} else if fileType == "xlsx" {
placeholderImage = UIImage(named: "xls")!
} else if fileType == "ppt" {
placeholderImage = UIImage(named: "ppt")!
} else if fileType == "pptx" {
placeholderImage = UIImage(named: "ppt")!
} else {
placeholderImage = UIImage(named: "plain")!
}
if let urlString = self.actionContentTemplate?.thumbnailURL {
let imageURL = URL(string: urlString)
SDWebImageManager.shared().loadImage(with: imageURL, options: [.continueInBackground, .scaleDownLargeImages], progress: nil) { (image, data, err, cacheType, finished, url) in
DispatchQueue.main.async {
if cellRow == self.tag {
self.activityIndicator?.stopAnimating()
self.imageView.image = image
UIAnimation.fadeTransitionImageView(self.imageView)
}
}
}
}
} else {
DispatchQueue.main.async {
self.activityIndicator?.stopAnimating()
self.imageView.image = placeholderImage
}
}
break
.....
I actually switched to loadImage method since the sd_setimage method was not working either.
SDWebImageManager.shared().loadImage(with: imageURL, options: [.continueInBackground, .scaleDownLargeImages], progress: nil) { (image, data, err, cacheType, finished, url) in
DispatchQueue.main.async {
if cellRow == self.tag {
//IF I COMMENT OUT THESE TWO LINES BELOW THE ISSUES STOP (I think it is only the self.imageView.image = image line that is causing issues)
// self.activityIndicator?.stopAnimating()
// self.imageView.image = image
UIAnimation.fadeTransitionImageView(self.imageView)
}
}
}
Can anyone kindly explain to me why this is occurring and what I can do to fix it?
EDIT - forgot to add these settings in app delegate to question:
//Settings for image caching
[[SDWebImageDownloader sharedDownloader] setShouldDecompressImages:NO];
[[[SDImageCache sharedImageCache] config] setShouldDecompressImages:NO];
[[[SDImageCache sharedImageCache] config] setShouldCacheImagesInMemory:NO];
[[[SDImageCache sharedImageCache] config] setMaxCacheSize:1024 * 1024 * 100];
[[[SDImageCache sharedImageCache] config] setMaxCacheAge:3600 * 24 * 7];
[[SDImageCache sharedImageCache] setMaxMemoryCost:1024 * 1024 * 15];