Проблемы с сохранением изображения из UIDocumentPickerViewController / .stopAccessingSecurityScopedResource () - PullRequest
0 голосов
/ 08 мая 2020

У меня есть viewcontroller, который представляет мой собственный класс 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 () все вместе, но это может вызвать проблемы? Есть идеи, как с этим справиться наилучшим образом?

1 Ответ

0 голосов
/ 08 мая 2020

Если я обновлю свой код для 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)
    }

Хорошее решение или лучшие идеи?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...