4

I'm developing an app for iPhone using a coverFlow view, when the app is building the cards it is using a UIView in order to add labels and other stuff. Then I convert the UIView into UIImage using the following code:

UIGraphicsBeginImageContext(imageView.bounds.size);
[imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

// returning the UIImage
return viewImage;

Every Time I redraw the coverflow I have a huge memory allocation increment, that never decreases even if I dealloc my coverFlow view.

I think the memory leak is in the code that I added, what do you think?

3 Answers3

2

There is no memory leak apparent in the code snippet you provided. That operation could not be performed on a background thread because of UIGraphicsBeginImageContext(), so you should have an NSAutoreleasePool in place (the return value of UIGraphicsGetImageFromCurrentContext() is autoreleased). Without further information, its impossible to tell where the memory leak could be - I suggest you look at whatever objects eventually own the viewImage object and make sure you are properly releasing the UIImage if you retain it.

Bryan Henry
  • 8,348
  • 3
  • 34
  • 30
0

Use drawViewHierarchyInRect:afterScreenUpdates: instead of renderInContext: it is 15x faster.

Performance comparison

You can see the comparison on this article.

Also, I have created a Swift extension for doing this: https://stackoverflow.com/a/32042439/517707

Community
  • 1
  • 1
Heberti Almeida
  • 1,440
  • 18
  • 27
0

Those who are coming here to convert multiple UIView to UIImage but getting memory leak. autoreleasepool can solve this issue. For example: To convert all subviews as UIImage

for subview in superView.subviews {
     autoreleasepool {
        let outputImage = subview.asImage()
     }
}


extension UIView {
    func asImage() -> UIImage? {
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(bounds: bounds)
            return renderer.image { rendererContext in
                layer.render(in: rendererContext.cgContext)
            }
        } else {
            UIGraphicsBeginImageContext(self.frame.size)
            self.layer.render(in:UIGraphicsGetCurrentContext()!)
            guard let image = UIGraphicsGetImageFromCurrentImageContext() else {
                return nil
            }
            UIGraphicsEndImageContext()
            guard let cgImage = image.cgImage else {
                return nil
            }
            return UIImage(cgImage: cgImage)
        }
    }
}


sagarthecoder
  • 137
  • 1
  • 9