UIImagePickerController记忆泄漏问题在Xcode 9中的Swift 4中。

3
在我的应用程序中,当我使用UIImagePickerController时发现了一个内存泄漏问题,一开始我以为是我的应用程序出了问题,但是在寻找解决方案时,我发现了苹果的一个示例程序,而且我也发现这个示例程序也存在相同的内存泄漏问题。
你可以在以下网址中找到这个示例:

https://developer.apple.com/library/content/samplecode/PhotoPicker/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010196

根据 UIImagePickerController 文档所述:

https://developer.apple.com/documentation/uikit/uiimagepickercontroller

在第5点中,他们说你必须使用委托对象来关闭图像选择器,在苹果的示例中,UIImagePickerDelegate正在执行关闭操作。
问题在于内存泄漏会浪费大约21 MB的内存,当你选择一张图片并处理它时。
没有内存泄漏的已使用内存

enter image description here

具有内存泄漏的已使用内存

enter image description here

内存泄漏

enter image description here

这是展示UIImagePickerController的代码:

@IBAction func showImagePickerForPhotoPicker(_ sender: UIBarButtonItem) {
    showImagePicker(sourceType: UIImagePickerControllerSourceType.photoLibrary, button: sender)
}

fileprivate func showImagePicker(sourceType: UIImagePickerControllerSourceType, button: UIBarButtonItem) {
    // If the image contains multiple frames, stop animating.
    if (imageView?.isAnimating)! {
        imageView?.stopAnimating()
    }
    if capturedImages.count > 0 {
        capturedImages.removeAll()
    }

    imagePickerController.sourceType = sourceType
    imagePickerController.modalPresentationStyle =
        (sourceType == UIImagePickerControllerSourceType.camera) ?
            UIModalPresentationStyle.fullScreen : UIModalPresentationStyle.popover

    let presentationController = imagePickerController.popoverPresentationController
    presentationController?.barButtonItem = button   // Display popover from the UIBarButtonItem as an anchor.
    presentationController?.permittedArrowDirections = UIPopoverArrowDirection.any

    if sourceType == UIImagePickerControllerSourceType.camera {
        // The user wants to use the camera interface. Set up our custom overlay view for the camera.
        imagePickerController.showsCameraControls = false

        // Apply our overlay view containing the toolar to take pictures in various ways.
        overlayView?.frame = (imagePickerController.cameraOverlayView?.frame)!
        imagePickerController.cameraOverlayView = overlayView
    }

    present(imagePickerController, animated: true, completion: {
        // Done presenting.
    })
}

这是用于关闭UIImagePickerController的委托方法中的代码:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    let image = info[UIImagePickerControllerOriginalImage]
    capturedImages.append(image as! UIImage)

    if !cameraTimer.isValid {
        // Timer is done firing so Finish up until the user stops the timer from taking photos.
        finishAndUpdate()
    } else {
        dismiss(animated: true, completion: nil)
    }
}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
    dismiss(animated: true, completion: {
        // Done cancel dismiss of image picker.
    })
}

fileprivate func finishAndUpdate() {
    dismiss(animated: true, completion: { [weak self] in
        guard let `self` = self else {
            return
        }

        if `self`.capturedImages.count > 0 {
            if self.capturedImages.count == 1 {
                // Camera took a single picture.
                `self`.imageView?.image = `self`.capturedImages[0]
            } else {
                // Camera took multiple pictures; use the list of images for animation.
                `self`.imageView?.animationImages = `self`.capturedImages
                `self`.imageView?.animationDuration = 5    // Show each captured photo for 5 seconds.
                `self`.imageView?.animationRepeatCount = 0   // Animate forever (show all photos).
                `self`.imageView?.startAnimating()
            }

            // To be ready to start again, clear the captured images array.
            `self`.capturedImages.removeAll()
        }
    })
}

我仍在寻找解决方案,任何帮助将不胜感激。


self.capturedImages.count should be \self`.capturedImages` - Brandon
你好Brandon,感谢你的回答。非常抱歉,我不明白你提出的修改想要实现什么目标。能否再解释清楚一些? - williammr
@williammr 我也遇到了同样的错误。你解决了这个问题吗? - Changnam Hong
1个回答

2

我曾经遇到过同样的问题,还有很多其他人也遇到了类似的问题,这个问题可以追溯到2008年,真的很疯狂。

不幸的是,我找到的最好答案是使用单例模式,这很糟糕。[即故意保留一个UIImagePickerController实例,以便每次选择图像时只需访问它]这是其他人建议的。

此外,我刚刚花了一个小时编写了这篇答案,其中包含使用单例模式的代码,但我无法避免内存泄漏[尽管我曾经一度认为我做对了]。也许我只是做错了 - 可以随意尝试。但我不会将我的功能失调的代码发布为答案。

最好的答案[这也是我解决问题的方法]是使用第三方pod /库。我使用了ImagePicker,它快速、免费、美观,没有内存泄漏![MIT许可证]

在这里查看: https://github.com/hyperoslo/ImagePicker


1
为什么这感觉像是广告呢...? - ChrisH
1
嗨,Chris!不是这样的!我与ImagePicker没有任何关联,但我目前正在我的iOS应用程序中使用它们,并且可以告诉您它与一个缺点非常适合 - 选择旧图片很困难,因为您必须滚动很多。否则,非常好用!祝好,Josh @ChrisH - Joshua Wolff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接