Как получить URL-адрес изображения, только что добавленного в PHPhotoLibrary

Я использую UIImagePickerController в двух случаях

  • чтобы выбрать существующее изображение в Фотобиблиотеке
  • чтобы сделать новое изображение

В первом случае, когда я выбираю форму изображения в библиотеке, я могу легко получить URL-адрес в методе делегирования:

- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    // Get the URL
    NSURL *url = [info valueForKey:UIImagePickerControllerReferenceURL];
    ...
}

Но когда я беру новое изображение, изображение еще не находится в библиотеке фотографий и еще не имеет URL. Поэтому мне сначала нужно добавить изображение в библиотеку. Но тогда, как получить URL-адрес нового актива?

Вот мой код, чтобы добавить изображение в Photo Library

- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    // Get the image
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

    // Add the image in the library
    [[PHPhotoLibrary sharedPhotoLibrary]

        performChanges:^
        {
            // Request creating an asset from the image.
            PHAssetChangeRequest *createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];

            // Get the URL of the new asset here ?
            ...
        }

        completionHandler:^(BOOL success, NSError *error)
        {
            if (!success) { ...; return; }

            // Get the URL of the new asset here ?
            ...
        }
    ];
}

Ответ 1

Я не нашел способ получить URL-адрес, но, возможно, localIdentifier может помочь вам выполнить ту же работу.

использование

NSString* localId = [[assetChangeRequest placeholderForCreatedAsset] localIdentifier];

чтобы получить локальный идентификатор и получить изображение позже.

__block NSString* localId;
// Add it to the photo library
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
    PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];

    if (self.assetCollection) {
        PHAssetCollectionChangeRequest *assetCollectionChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:self.assetCollection];
        [assetCollectionChangeRequest addAssets:@[[assetChangeRequest placeholderForCreatedAsset]]];
    }
    localId = [[assetChangeRequest placeholderForCreatedAsset] localIdentifier];
} completionHandler:^(BOOL success, NSError *error) {
    PHFetchResult* assetResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[localId] options:nil];
    if (!success) {
        NSLog(@"Error creating asset: %@", error);
    } else {
        PHFetchResult* assetResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[localId] options:nil];
        PHAsset *asset = [assetResult firstObject];
        [[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
            UIImage* newImage = [UIImage imageWithData:imageData];
            self.imageView.image = newImage;
        }];
    }
}];

Ответ 2

Если мы используем ALAssetsLibrary, очень просто сохранить изображение в фотоальбоме и получить его URL:

    // Get the image
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

    // Add the image in the Photo Library
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    [library writeImageToSavedPhotosAlbum: [image CGImage]
                              orientation: (ALAssetOrientation)[image imageOrientation]
                          completionBlock: ^(NSURL *assetURL, NSError *error)
    {
        if (error)
        {
            NSLog( @"error: %@", error );
        }
        else
        {
            NSLog( @"assetURL = %@", assetURL );
        }
    }];

Но на удивление кажется невозможным сделать то же самое с новой PHPhotoLibrary!

Решение иметь тот же результат с PHPhotoLibrary всегда приветствуется.

Ответ 3

Мне не нравится это исправление, так как это может привести к состоянию гонки. До сих пор я не могу придумать лучшего решения. Если кто-то мне понравится это услышать:) В любом случае, вот Свифт-версия ответа Ригеля Чена

import Photos

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {

    if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {

        var localId:String?
        let imageManager = PHPhotoLibrary.sharedPhotoLibrary()

        imageManager.performChanges({ () -> Void in

            let request = PHAssetChangeRequest.creationRequestForAssetFromImage(image)
            localId = request.placeholderForCreatedAsset?.localIdentifier

            }, completionHandler: { (success, error) -> Void in
                dispatch_async(dispatch_get_main_queue(), { () -> Void in

                    if let localId = localId {

                        let result = PHAsset.fetchAssetsWithLocalIdentifiers([localId], options: nil)
                        let assets = result.objectsAtIndexes(NSIndexSet(indexesInRange: NSRange(location: 0, length: result.count))) as? [PHAsset] ?? []

                        if let asset = assets.first {
                            // Do something with result
                        }
                    }
                })
        })
    }
}

Ответ 4

Swift 4, который работает для меня, чтобы получить URL-адрес последнего изображения в Photo Library:

let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
let fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions).lastObject
PHImageManager().requestAVAsset(forVideo: fetchResult!, options: nil, resultHandler { (avurlAsset, _, _) in
    if let newObj = avurlAsset as? AVURLAsset {
        print(newObj.url)
    }
})

Надеюсь, поможет!

Ответ 5

[Swift 4] Этот метод может обрабатывать как изображение, так и видео, наслаждайтесь :)

func getURL(of asset: PHAsset, completionHandler : @escaping ((_ responseURL : URL?) -> Void)) {

    if asset.mediaType == .image {
        let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
        options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
            return true
        }
        asset.requestContentEditingInput(with: options, completionHandler: { (contentEditingInput, info) in
            completionHandler(contentEditingInput!.fullSizeImageURL)
        })
    } else if asset.mediaType == .video {
        let options: PHVideoRequestOptions = PHVideoRequestOptions()
        options.version = .original
        PHImageManager.default().requestAVAsset(forVideo: asset, options: options, resultHandler: { (asset, audioMix, info) in
            if let urlAsset = asset as? AVURLAsset {
                let localVideoUrl = urlAsset.url
                completionHandler(localVideoUrl)
            } else {
                completionHandler(nil)
            }
        })
    }
}

Ответ 6

Получить URL изображения:

- (void)processImage:(UIImage*)image type:(NSString*)mimeType forCallbackId:(NSString*)callbackId
    {
        __block NSString* localId;

        // Add it to the photo library
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];

            localId = [[assetChangeRequest placeholderForCreatedAsset] localIdentifier];
        } completionHandler:^(BOOL success, NSError *err) {
            if (!success) {
                NSLog(@"Error saving image: %@", [err localizedDescription]);
            } else {
                PHFetchResult* assetResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[localId] options:nil];
                PHAsset *asset = [assetResult firstObject];
                [[PHImageManager defaultManager] requestImageDataForAsset:asset
                                                                  options:nil
                                                            resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
                    NSURL *fileUrl = [info objectForKey:@"PHImageFileURLKey"];
                    if (fileUrl) {
                        NSLog(@"Image path: %@", [fileUrl relativePath]);
                    } else {
                        NSLog(@"Error retrieving image filePath, heres whats available: %@", info);
                    }
                }];
            }
        }];
    }