PHImageManager.requestImageForAsset возвращает нуль при создании эскиза для видео

Для некоторых видеороликов requestImageForAsset завершает работу с UIImage, который равен нулю. Для других видео он отлично работает, и я пока не понял, почему.

func createThumbnailForVideo(video: PHAsset) -> Future<NSURL> {
    let promise = Promise<NSURL>()
    let options = PHImageRequestOptions()
    options.synchronous = true

    imageManager.requestImageForAsset(video, targetSize: CGSizeMake(640, 640), contentMode: .AspectFill, options: options) { (image:UIImage!, info) -> Void in

        if image == nil {
            println("Error: Couldn't create thumbnail for video")
            promise.error(MyErrors.videoThumb())
        } else {
            if let thumbURL = self.savePhotoAsTemporaryFile(image) {
                promise.success(thumbURL)
            } else {
                promise.error(MyErrors.videoThumb())
            }
        }
    }

    return promise.future
}

Я также возвращаю информацию для запроса, но я не знаю, как интерпретировать информацию:

[PHImageResultIsDegradedKey: 0, PHImageResultWantedImageFormatKey: 4037, PHImageResultIsPlaceholderKey: 0, PHImageResultIsInCloudKey: 0, PHImageResultDeliveredImageFormatKey: 9999]

Ответ 1

У меня была такая же проблема сегодня. Для меня мне пришлось добавить опцию для загрузки изображения, если это необходимо. Я думаю, что менеджер изображений имел доступную версию уменьшенного размера, но, поскольку я не разрешал ему получать фактическое изображение из сети, он возвратил бы нуль во втором обратном вызове. Поэтому, чтобы исправить это, я создал объект PHImageRequestOptions() следующим образом:

var options = PHImageRequestOptions()
options.networkAccessAllowed = true

Затем отправьте это как параметр с вашим запросом:

PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: size, contentMode: PHImageContentMode.AspectFill, options: options) { (image, info) -> Void in
    if (image != nil) {
        cell.imageView.image = image
    }
}

Как только я это сделал, второй обратный вызов был не нулем. Я думаю, что по-прежнему неплохо защищаться от наличия нулевого изображения, поэтому вы не устанавливаете изображение с изображением на ноль. Я не думаю, что вы можете предположить, что изображение всегда будет там. Надеюсь, это поможет!

РЕДАКТИРОВАТЬ: Просто уточнить. В моем случае для каждого запроса замыкание будет вызываться дважды. В первый раз изображение было не ноль, а во второй раз. Я думаю, что это потому, что была доступна версия с миниатюрным размером, но полного размера не было. Для получения полноразмерного изображения необходим сетевой доступ.

Ответ 2

Наконец-то я нашел проблему. ContentMode был .AspectFill, но должен быть .AspectFit. Думаю, я мог бы заставить его работать, изменив PHImageRequestOptionsDeliveryMode и PHImageRequestOptionsResizeMode, если я прочитаю комментарии. Однако .AspectFit был тем, что я искал.

enum PHImageContentMode : Int {

// Fit the asked size by maintaining the aspect ratio, the delivered image may not necessarily be the asked targetSize (see PHImageRequestOptionsDeliveryMode and PHImageRequestOptionsResizeMode)
case AspectFit
// Fill the asked size, some portion of the content may be clipped, the delivered image may not necessarily be the asked targetSize (see PHImageRequestOptionsDeliveryMode && PHImageRequestOptionsResizeMode)
case AspectFill

}

Ответ 3

У меня была аналогичная проблема, но это было для фотографий, а не для видео. Я пропустил указать тип носителя.

self.assetsFetchResults = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];

Выше была решена проблема для меня.