4

I am loading images from assets in my UITableView and I noticed I get a memory leak related to the CGImage I load from the defaultAssetRepresentation.fullResolutionImage.CGImage.takeunretainedValue.

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(kReviewDisplayCell, forIndexPath: indexPath) as ReviewDisplayCollectionViewCell
    let asset = assets.objectAtIndex(indexPath.row) as ALAsset
    var cgImage = asset.defaultRepresentation().fullResolutionImage().takeUnretainedValue()
    var orientation:UIImageOrientation?
    var orientationValue:NSNumber = asset.valueForProperty(ALAssetPropertyOrientation) as NSNumber
    orientation  = self.correctOrientation(orientationValue)
    var image = UIImage(CGImage: cgImage, scale: 0.5, orientation: orientation!)
    cell.imageView.image = image

    return cell
}

According to memory leak instruments the leak appears to be related to: NSPathStore2 object. Responsible frame: +[NSPathStore2 pathStoreWithCharacters:Length:]

The above function is called earlier in the stack by: -[ALAssetRepresentation _fileDescriptor] then -[PLGateKeeperClient fileDescriptorForAssetURL:]

I apologize I don't have enough reputation to post my screen shot of the instruments.

On the allocations instrument there is always CGImage retained from the UITableViewController even after the viewcontroller is dismissed by the navigation control and I can't figure out if there is a strong reference to it from somewhere. Is there a way to manually release the CGImage reference while using ARC? I tried putting the above code in an autoreleasepoool{} but it did not work. Thank you in advance for the help.

Zigii Wong
  • 7,766
  • 8
  • 51
  • 79
joanna cheung
  • 161
  • 3
  • 9

1 Answers1

1

For those who still haven't found what they're looking for, and stumble upon this question, using CGImage needs to be wrapped with autorelease, probably something like:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(kReviewDisplayCell, forIndexPath: indexPath) as ReviewDisplayCollectionViewCell
    let asset = assets.objectAtIndex(indexPath.row) as ALAsset
    autoreleasepool {
        var cgImage = asset.defaultRepresentation().fullResolutionImage().takeUnretainedValue()
        var orientation:UIImageOrientation?
        var orientationValue:NSNumber = asset.valueForProperty(ALAssetPropertyOrientation) as NSNumber
        orientation  = self.correctOrientation(orientationValue)
        var image = UIImage(CGImage: cgImage, scale: 0.5, orientation: orientation!)
        cell.imageView.image = image
    }   
    return cell
}

See this answer for details.

Stickley
  • 4,561
  • 3
  • 30
  • 29
  • 1
    Great answer! However, I couldn't edit it to "autoreleasepool", since that edit is below the 6 character limit at StackOverflow. – Linus Mar 06 '20 at 13:15