Получение URL-адреса снимка, сделанного камерой с помощью Photos Framework

У меня есть приложение, которое использует UIImagePickerController для получения изображений как с камеры, так и из библиотеки фотографий. В делегате выбора изображений я хочу только сохранить NSURL (UIImagePickerControllerReferenceURL) выбранного изображения для экономии памяти. Когда пользователю необходимо увидеть изображение позже, я загружаю его с помощью PHCachingImageManager прямо из библиотеки фотографий.

Теперь - все это прекрасно работает с изображениями, которые пользователь выбирает из библиотеки, но не с изображениями, снятыми непосредственно камерой (так как URL отсутствует). В настоящее время я пытаюсь сохранить изображение с помощью PHAsset, но я не знаю, как получить NSURL для сохраненного изображения.

Вот чем я занимался:

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
{
    picker.dismissViewControllerAnimated(true, completion: nil)

    let pickedImage = info[UIImagePickerControllerOriginalImage] as! UIImage

    if picker.sourceType == .Camera
    {
        // When taking a picture with the camera, store it in the user roll
        PHPhotoLibrary.sharedPhotoLibrary().performChanges(
            { () -> Void in

                // save the image
                PHAssetCreationRequest.creationRequestForAssetFromImage(pickedImage)

                // TODO how to get the asset url

            }, completionHandler:
            { (finished, error) -> Void in
                if (finished)
                {

                }
            }
        )

    }
    else
    {
        let pickedImageUrl: NSURL? = info[UIImagePickerControllerReferenceURL] as? NSURL

        currentImageUrl = pickedImageUrl

        currentImage = pickedImage

        toggleImageInfoView(true)
        toggleMapState(true)
    }


}

Любые идеи, как получить URL сохраненного изображения?

Бест, Георг

2 ответа

Решение

ОБНОВЛЕНИЕ: Похоже, я нашел ответ на эту проблему.

Шаг 1: я сохраняю изображение на камеру

UIImageWriteToSavedPhotosAlbum(image.image, self, #selector(cameraImageSavedAsynchronously), nil)

это делается асинхронно, поэтому убедитесь, что селектор установлен после завершения операции.

Шаг 2: После завершения операции я делаю следующее:

func fetchLastImage(completion: (localIdentifier: String?) -> Void)
{
    let fetchOptions = PHFetchOptions()
    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
    fetchOptions.fetchLimit = 1

    let fetchResult = PHAsset.fetchAssetsWithMediaType(.Image, options: fetchOptions)
    if (fetchResult.firstObject != nil)
    {
        let lastImageAsset: PHAsset = fetchResult.firstObject as! PHAsset
        completion(localIdentifier: lastImageAsset.localIdentifier)
    }
    else
    {
        completion(localIdentifier: nil)
    }
}

Я извлекаю последнее изображение в рулоне камеры с помощью PHAsset и сохраняю локальный идентификатор изображения. Это не URL, а уникальный идентификатор, который не изменяется. Таким образом, вы можете получить доступ к сохраненному изображению идеально.

Надеюсь, что это помогает другим!

Я с тобой согласен.

но, если Exif изображения имеет дату более раннюю.

let fetchResult = PHAsset.fetchAssetsWithMediaType(.Image, options: fetchOptions)
fetchResult.firstObject

fetchResult.firstObject - это не тот, который вы только что сохранили.

может быть, вы можете изменить fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false) в key: "modificationDate"

Кстати, я нашел другой способ:

 __block PHObjectPlaceholder *placeholderAsset = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
    PHAssetChangeRequest *newAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
    newAssetRequest.location = location;
    newAssetRequest.creationDate = [NSDate date];
    placeholderAsset = newAssetRequest.placeholderForCreatedAsset;
} completionHandler:^(BOOL success, NSError *error) {
    if(success){
        PHAsset *asset = [self getAssetFromlocalIdentifier:placeholderAsset.localIdentifier];
        completionBlock(asset, YES);
    } else {
        completionBlock(nil, NO);
    }
}];

можно получить новый PHAsset.

Я обновил ответ, включив в него возврат любого типа актива, а также более простой / чистый способ возврата актива.

Нет необходимости в проводнике соревнований.

func fetchLastAsset() -> PHAsset? {
    let fetchOptions = PHFetchOptions()
    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
    fetchOptions.fetchLimit = 1
    let fetchResult = PHAsset.fetchAssets(with: fetchOptions)
    return fetchResult.firstObject
}
Другие вопросы по тегам