0

我有一个显示我的自定义 ImagePicker 类的视图控制器。提供的选项之一是使用 UIDocumentPickerViewController 从“文件”中选择图像。选择图像工作正常,但我想关闭安全资源符合建议。

ProjectimagePicker {
(...)
            let documentsPicker = UIDocumentPickerViewController(documentTypes: ["public.image", "public.jpeg", "public.png"], in: .open)
            documentsPicker.delegate = self
            documentsPicker.allowsMultipleSelection = false
            documentsPicker.modalPresentationStyle = .fullScreen
            self.presentationController?.present(documentsPicker, animated: true, completion: nil)
}

//MARK: - Ext. Delegate DocumentPicker
extension ProjectImagePicker: UIDocumentPickerDelegate {
    public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        guard controller.documentPickerMode == .open, let url = urls.first, url.startAccessingSecurityScopedResource() else { return }
        defer {
            DispatchQueue.main.async {
                url.stopAccessingSecurityScopedResource()
            }
             }

        guard let image = UIImage(contentsOfFile: url.path) else { return }
        self.delegate?.didSelect(image: image)
        controller.dismiss(animated: true)
    }

    public func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
        controller.dismiss(animated: true)
    }
}

在调用选择器类的 viewController 中:

//MARK: - Delegate ProjectImagePicker
extension ProjectDetailsViewController: ProjectImagePickerDelegate {
    func didSelect(image: UIImage?) {
        if let image  = image {
            selectedImage = image
            projectImageView.image = image
        }
    }
}

我通过在 stopAccessingSecurityScopedResource() 周围包装调度调用来规避部分问题。图像被发回(委托)并呈现在 viewController 中。但是当我最终保存(写入文档目录)我的项目和该图像(selectedImage)时,我得到了安全错误

2020-05-08 13:54:04.429936+0200 ProjectS[3482:1339708] [ProjectS] createDataWithMappedFile:1524:  'open' failed '/private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/10.JPEG'  error = 1 (Operation not permitted)

因此,显然图像仍在引用文档选择器中的 URL。我可以尝试在 didPickDocumentsAt 方法中临时保存图像,但这看起来很难看。或者我可以省略一起调用 stopAccessingSecurityScopedResource() ,但这可能会导致问题?关于如何以最佳方式处理此问题的任何想法?

4

1 回答 1

0

如果我以复制图像的方式更新 didPickDocumentsAt 的代码,则所有操作都按预期工作

//MARK: - Ext. Delegate DocumentPicker
extension ProjectImagePicker: UIDocumentPickerDelegate {
    public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        guard controller.documentPickerMode == .open, let url = urls.first, url.startAccessingSecurityScopedResource() else { return }
        defer {
            DispatchQueue.main.async {
                url.stopAccessingSecurityScopedResource()
            }
             }

        //Need to make a new image with the jpeg data to be able to close the security resources!
        guard let image = UIImage(contentsOfFile: url.path), let imageCopy = UIImage(data: image.jpegData(compressionQuality: 1.0)!) else { return }

        self.delegate?.didSelect(image: imageCopy)
        controller.dismiss(animated: true)
    }

好的解决方案,还是更好的想法?

于 2020-05-08T12:30:41.980 回答