Доступ к PHPhotoLibrary, когда приложение находится в фоновом режиме

У меня есть NSURLDownloadTask, который успешно загружает файлы в фоновом режиме (большие изображения или видеофайлы). И я успешно копирую URL-адреса и вызываю эту функцию, чтобы сохранить свой URL-адрес в библиотеке фотографий. Как видите, я хотел бы отправить UILocalNotification, чтобы уведомить пользователя о том, что его загрузка завершена.

Моя проблема в том, что хотя PHPhotoLibrary.sharedPhotoLibrary().performChanges будет вызываться, пока приложение находится в фоновом режиме, блок завершения не будет. (однако это вызвано тем, что приложение возвращается на передний план). Я попытался прокомментировать захват основного потока, чтобы увидеть, помогло ли это, но это не помогло. И я не хочу отправлять локальное уведомление перед блоком завершения, потому что я хочу сообщить пользователю в уведомлении об успешной/неудачной загрузке.

Я полагаю, что могу отправить уведомление методом NSURLDownloadDelegateTask. Это позволит пользователю узнать, что файл был успешно загружен, но не будет ли успешно сохранено его на своих фотографиях. И я бы не хотел, чтобы мой пользователь сказал, что их загрузка прошла успешно, а затем они не смогли найти его в своей библиотеке фотографий.

Вот мой код, в котором я получаю доступ к библиотеке фотографий и изменяю ее.

func saveURLToPhotosLibrary(url: NSURL, fileName: String) {

        if let fileExtension = url.pathExtension {
            PHPhotoLibrary.sharedPhotoLibrary().performChanges({

                let fileUnmanagedIDTag = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension, nil)

                let fileIDTag = fileUnmanagedIDTag?.takeRetainedValue()
                if let fileUTType = fileIDTag {
                    if UTTypeConformsTo(fileUTType, kUTTypeImage) {
                        PHAssetChangeRequest.creationRequestForAssetFromImageAtFileURL(url)
                    } else if UTTypeConformsTo(fileUTType, kUTTypeMovie){
                        PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(url)
                    }
                } else {
                    print("Error getting type of file from download")
                }

            }) { (success, error) in
                //dispatch_async(dispatch_get_main_queue(), {

                    if success {
                        print("finished")
                        self.sendLocalNotification(downloadSuccessful: true, error : nil, fileName: fileName)
                    } else {
                        if let error = error {
                            self.sendLocalNotification(downloadSuccessful: false, error : error, fileName: fileName)
                        }
                    }
                //})
            }
        }
    }

person NSGangster    schedule 30.07.2016    source источник


Ответы (1)


Хорошо нашел мое рабочее решение. Выяснил, что приложение немедленно приостанавливается после отсутствия кода для запуска, поэтому приложение приостанавливается к тому времени, когда мой обработчик завершения готов к вызову. Я использовал общий экземпляр UIApplications для создания новой фоновой задачи. Это дает моему приложению достаточно времени для вызова обработчика завершения. Затем я завершаю фоновую задачу, как только получаю уведомление.

func saveURLToPhotosLibrary(url: NSURL, fileName: String) {

    //Returns id to later be passed into method that ends task.
    let backgroundID : Int = UIApplication.sharedApplication().beginBackgroundTaskWithName("Save to Photo Library Task") {
        print("Background task expired")
    }

    if let fileExtension = url.pathExtension {
        PHPhotoLibrary.sharedPhotoLibrary().performChanges({

            let fileUnmanagedIDTag = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension, nil)

            let fileIDTag = fileUnmanagedIDTag?.takeRetainedValue()
            if let fileUTType = fileIDTag {
                if UTTypeConformsTo(fileUTType, kUTTypeImage) {
                    PHAssetChangeRequest.creationRequestForAssetFromImageAtFileURL(url)
                } else if UTTypeConformsTo(fileUTType, kUTTypeMovie){
                    PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(url)
                }
            } else {
                print("Error getting type of file from download")
            }


        }) { (success, error) in

                if success {
                    print("finished")
                    self.sendLocalNotification(downloadSuccessful: true, error : nil, fileName: fileName)
                } else {
                    if let error = error {
                        self.sendLocalNotification(downloadSuccessful: false, error : error, fileName: fileName)
                    }
                }
            //End background task here passing in id of task from earlier.
            UIApplication.sharedApplication().endBackgroundTask(backgroundID)
        }
    }
}
person NSGangster    schedule 02.08.2016
comment
К вашему сведению, одна из причин, по которой никто не ответил, заключается в том, что ваш вопрос был ошибочно помечен как NSURLDownload, который является устаревшим API только для OS-X, а не NSURLSession. :-) - person dgatwood; 03.08.2016
comment
Да, мой плохой, я удалю тег. Думал, что NSURLDownloadTask - person NSGangster; 03.08.2016