UIImagePickerController 在 iOS 11 上泄漏
UIImagePickerController leaking on iOS 11
我已经配置了 UIImagePickerController
以独立拍摄图像和录制视频。 UIImagePickerController
直接从 @IBAction
调用(由 UIButton
)。我在 imagePickerController
委托方法中从视频中收到 UIImage
和 URL
并打印它们以供测试。
稍等片刻(10 秒)后,我在 select Xcode 的 "View Memory Graph History" 中看到在两个测试用例中我都有内存泄漏和循环引用.如果有人认为这是一个 Xcode 错误,我也可以在 Instruments 中看到这些内存泄漏。
我录制视频时出现这种情况:
当我拍照时会出现这种情况:
您可以在 iOS 11.2 设备上使用此代码重现此结果(我认为模拟器无法运行):
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)
}
}
现在我的问题是:我可以通过一些变通办法解决这些问题,还是我在代码中做错了什么,这是 Apple 的错误,我应该忽略它吗?
编辑:如果有人想看一看整个项目:https://github.com/ph1ps/UIImagePickerLeak
我添加了一些代码来证明没有内存泄漏。您可以通过我的代码或内存图来判断它。我已经提出了拉取请求。
我会说忽略你看到的 "leaks"。虽然,我没有任何代码来支持这一点,但我确实有一些在工作中发现和修复内存泄漏的经验。根据我的经验,当你发现泄漏时,你会寻找确凿的证据。因此,对于内存图历史记录,如果有数百或数千个某种类型的实例泄漏,我会怀疑可能存在内存泄漏。这也适用于移动应用程序。从我从您的屏幕截图中可以看出,您最多泄漏 1k,这(假设甚至有泄漏)非常微不足道。这样看来,你真的没有漏水。
关于是否存在泄漏,我看到了各种相互矛盾的信息。
首先……它的前后矛盾让很多人感到沮丧。
我完全看到了使用 UIImagePickerController 时的保留。 IS 有某种问题。我有一个用户配置文件编辑器,它有两个地方可以 take/select 图像(一个用于人,一个用于他的车辆)。当我对两者使用完全相同的代码时,一个发布就好了,而我的 profileEditViewController deinits 就好了。当我使用另一个时,即使取消选择图像,它也不会释放,我的控制器也不会取消初始化。完全相同的代码。两个地方都是100%。
我认为这归结为委托保留,但我尝试了不设置委托(因此使其基本上无用)并且同样的结果显而易见。仅仅启动第二个 UIImagePickerController 就导致了保留锁,甚至为第二个声明了一个完整的其他变量。我可以通过简单地从不启动第二个选择器来让我的控制器取消初始化,但是内存不会下降。
即使与我的控制器断开连接,它也会保留。如果在生产代码中遵循 Apple 最严格的示例,这有点愚蠢 :(
我已经配置了 UIImagePickerController
以独立拍摄图像和录制视频。 UIImagePickerController
直接从 @IBAction
调用(由 UIButton
)。我在 imagePickerController
委托方法中从视频中收到 UIImage
和 URL
并打印它们以供测试。
稍等片刻(10 秒)后,我在 select Xcode 的 "View Memory Graph History" 中看到在两个测试用例中我都有内存泄漏和循环引用.如果有人认为这是一个 Xcode 错误,我也可以在 Instruments 中看到这些内存泄漏。
我录制视频时出现这种情况:
当我拍照时会出现这种情况:
您可以在 iOS 11.2 设备上使用此代码重现此结果(我认为模拟器无法运行):
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)
}
}
现在我的问题是:我可以通过一些变通办法解决这些问题,还是我在代码中做错了什么,这是 Apple 的错误,我应该忽略它吗?
编辑:如果有人想看一看整个项目:https://github.com/ph1ps/UIImagePickerLeak
我添加了一些代码来证明没有内存泄漏。您可以通过我的代码或内存图来判断它。我已经提出了拉取请求。
我会说忽略你看到的 "leaks"。虽然,我没有任何代码来支持这一点,但我确实有一些在工作中发现和修复内存泄漏的经验。根据我的经验,当你发现泄漏时,你会寻找确凿的证据。因此,对于内存图历史记录,如果有数百或数千个某种类型的实例泄漏,我会怀疑可能存在内存泄漏。这也适用于移动应用程序。从我从您的屏幕截图中可以看出,您最多泄漏 1k,这(假设甚至有泄漏)非常微不足道。这样看来,你真的没有漏水。
关于是否存在泄漏,我看到了各种相互矛盾的信息。
首先……它的前后矛盾让很多人感到沮丧。
我完全看到了使用 UIImagePickerController 时的保留。 IS 有某种问题。我有一个用户配置文件编辑器,它有两个地方可以 take/select 图像(一个用于人,一个用于他的车辆)。当我对两者使用完全相同的代码时,一个发布就好了,而我的 profileEditViewController deinits 就好了。当我使用另一个时,即使取消选择图像,它也不会释放,我的控制器也不会取消初始化。完全相同的代码。两个地方都是100%。
我认为这归结为委托保留,但我尝试了不设置委托(因此使其基本上无用)并且同样的结果显而易见。仅仅启动第二个 UIImagePickerController 就导致了保留锁,甚至为第二个声明了一个完整的其他变量。我可以通过简单地从不启动第二个选择器来让我的控制器取消初始化,但是内存不会下降。
即使与我的控制器断开连接,它也会保留。如果在生产代码中遵循 Apple 最严格的示例,这有点愚蠢 :(