How to get the URL of an image just added in PHPhotoLibrary

后端 未结 6 884
臣服心动
臣服心动 2020-12-30 03:11

I am using the UIImagePickerController in two cases

  • to select an existing image in the Photo Library
  • to take a new picture

In the first

相关标签:
6条回答
  • 2020-12-30 03:38

    If we use the ALAssetsLibrary, it is very simple to save a picture in the Photo Album and get its 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 );
            }
        }];
    

    But surprisingly it seems not possible to do the same thing with the new PHPhotoLibrary!

    A solution to have the same result with PHPhotoLibrary is always welcome.

    0 讨论(0)
  • 2020-12-30 03:48

    I didn't find the way to get URL, but maybe localIdentifier can help you do the same work.

    use

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

    to get the local ID and get the image later.

    __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;
            }];
        }
    }];
    
    0 讨论(0)
  • 2020-12-30 03:50

    I don't like this fix, as this could result in a race condition. So far I can't think of a better solution. If someone does I'd love to hear it :) Either way, here is a Swift-version of Rigel Chen's answer

    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
                            }
                        }
                    })
            })
        }
    }
    
    0 讨论(0)
  • 2020-12-30 04:01

    Swift 4 solution that works for me to get the url of last image in 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)
        }
    })
    

    Hope it helps!

    0 讨论(0)
  • 2020-12-30 04:02

    Retrieve image 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);
                        }
                    }];
                }
            }];
        }
    
    0 讨论(0)
  • 2020-12-30 04:03

    [Swift 4] This method can handle both image and video, enjoy :)

    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 讨论(0)
提交回复
热议问题