web-dev-qa-db-fra.com

Comment obtenir l'URL d'une image qui vient d'être ajoutée dans PHPhotoLibrary

J'utilise UIImagePickerController dans deux cas

  • sélectionner une image existante dans la photothèque
  • prendre une nouvelle photo

Dans le premier cas, lorsque je choisis une image dans la bibliothèque, je peux facilement obtenir l'URL dans la méthode déléguée:

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

Mais lorsque je prends une nouvelle photo, celle-ci ne figure pas encore dans la photothèque et ne contient pas encore d'URL. Donc, je dois d'abord ajouter l'image dans la bibliothèque. Mais alors, comment obtenir l'URL du nouvel actif?

Voici mon code pour ajouter l'image dans la photothèque

- (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 ?
            ...
        }
    ];
}
14
PatrickV

Je n'ai pas trouvé le moyen d'obtenir l'URL, mais peut-être que localIdentifier peut vous aider à faire le même travail.

utilisation

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

pour obtenir l'ID local et obtenir l'image plus tard.

__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;
        }];
    }
}];
9
Rigel Chen

Je n'aime pas ce correctif, car cela pourrait entraîner une situation de concurrence critique. Jusqu'à présent, je ne peux pas penser à une meilleure solution. Si quelqu'un le faisait, j'aimerais l'entendre :) Quoi qu'il en soit, voici une version rapide de la réponse de Rigel Chen

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
                        }
                    }
                })
        })
    }
}
1
Kevin R

Si nous utilisons ALAssetsLibrary, il est très simple d’enregistrer une photo dans l’Album photo et d’obtenir son 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 );
        }
    }];

Mais étonnamment, il ne semble pas possible de faire la même chose avec la nouvelle PHPhotoLibrary!

Une solution pour obtenir le même résultat avec PHPhotoLibrary est toujours la bienvenue.

1
PatrickV

[Swift 4] Cette méthode peut gérer à la fois l'image et la vidéo, profitez-en :)

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)
            }
        })
    }
}
0
Amos

Récupérer l'URL de l'image:

- (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);
                    }
                }];
            }
        }];
    }
0
user1495323

Swift 4 solution qui fonctionne pour moi pour obtenir l'URL de la dernière image dans la photothèque :

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)
    }
})

J'espère que ça aide!

0
Tung Fam