Thursday, February 8, 2018

UIImagePickerController leaking on iOS 11

Leave a Comment

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

2 Answers

Answers 1

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.

Answers 2

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

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment