ph1psG
ph1psG

Reputation: 738

UIImagePickerController leaking on iOS 11

I've configured my UIImagePickerController for taking an image and for recording a video both independently. The UIImagePickerController is directly called from an @IBAction (by a UIButton). I receive both UIImage and URL from the video in the imagePickerController delegate method and print them for testing purposes.

After waiting a little while (10 seconds) I select Xcode's "View Memory Graph History" in which I can see that in both testing cases I have memory leaks and also cyclic references. I can also see those memory leaks in Instruments if someone thinks it's an Xcode bug.

This happens when I record a video:

memory leaks video

And this happens when I take a picture:

memory leaks photo

You can reproduce this results with this code on a iOS 11.2 device (I don't think simulators would work):

import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBAction func takePhoto(_ sender: Any) {

        let picker = UIImagePickerController()
        picker.delegate = self
        picker.sourceType = .camera
        picker.allowsEditing = false

        self.present(picker, animated: true, completion: nil)
    }

    @IBAction func recordVideo(_ sender: Any) {

        let picker = UIImagePickerController()
        picker.delegate = self
        picker.sourceType = .camera
        picker.allowsEditing = false
        picker.mediaTypes = ["public.movie"]
        picker.videoQuality = .typeHigh

        self.present(picker, animated: true, completion: nil)
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) {

        picker.dismiss(animated: true, completion: nil)

        if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
            print(image.size)
        }

        if let video = info[UIImagePickerControllerMediaURL] as? URL {
            print(video.path)
        }
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }

}

Now my question is: Can I fix those with some workaround or am I doing something wrong in my code, is this a bug by Apple, should I just ignore it?

Edit: If anyone wants to take a look at the whole project: https://github.com/ph1ps/UIImagePickerLeak

Upvotes: 9

Views: 1315

Answers (3)

chornbe
chornbe

Reputation: 1164

I'm seeing all sorts of conflicting info on whether there's a leak or not.

First off... there is, it's the inconsistency of it that's frustrating people en masse.

I'm totally seeing retention when using UIImagePickerController. There IS some sort if issue with it. I've got a user profile editor that has two places to take/select an image (one for the person, one for his vehicle). When I use the EXACT same code for both, one releases just fine, and my profileEditViewController deinits just fine. When I use the other, even to cancel selection of an image, it does not release and my controller never deinits. Exact same code. 100% in both places.

I thought it came down to delegate retention, but I experimented with not setting delegation (thus rendering it basically useless) and the same results were plainly evident. Just initiating the second UIImagePickerController caused a retention lock, even declaring a whole other variable for the second one. I can get my controller to deinit by simply never initiating the second picker, however the memory doesn't drop.

It's retaining, even if disconnected from my controller. It's kind of silly when that's the case following Apple's strictest examples to the letter in production code :(

Upvotes: 1

Jon Thoms
Jon Thoms

Reputation: 10749

I would say just ignore the "leaks" you are seeing. While, I don't have any code to back this up, I do have some experience finding and fixing memory leaks on-the-job. In my experience, when you're finding leaks, you look for smoking guns. So for the memory graph history, I would suspect that there might be a memory leak if there were hundreds or thousands of instances of some type leaked. This goes for mobile apps as well. From what I can see from your screenshots, you're leaking at most 1k, which (assuming there even is a leak) is pretty trivial. As such, you really don't appear to have a leak.

Upvotes: 9

Andy Darwin
Andy Darwin

Reputation: 478

I add some code to prove there is no memory leak. You can judge it either by my code or memory graph. I've already made a pull request.

https://github.com/Andy1984/UIImagePickerLeak

Upvotes: 1

Related Questions