Retrieving the URL of a snapshot using the Photos Framework

I have an application that uses the UIImagePickerController to extract images from both the camera and the photo library. In the image picker delegate, I want to save the NSURL ( UIImagePickerControllerReferenceURL ) of the selected image to save memory. When the user needs to see the image later, I upload it using PHCachingImageManager directly from the photo library.

Now - all this works great with photos that the user selects from the library, but not with photos taken directly by the camera (since there is no URL). I am currently trying to save an image using PHAsset , but I do not know how to get the NSURL image save.

This is what I did:

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

Any ideas on how to get the URL of the saved image?

Best, Georg

+7
source share
3 answers

UPDATE: It seems I found the answer to this problem.

Step 1: I save the image on the camera

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

this is done asynchronously, so be sure to set the selector when the operation is complete.

Step 2: When the operation is completed, I do the following:

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

I take the last image in the camera frame using PHAsset and save the local image identifier. This is not a URL, but a unique identifier that does not change. This way you can access the saved image.

Hope this helps others!

+2
source

I agree with you.

but if Image Exif has a date earlier.

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

fetchResult.firstObject is not the one you just saved.

maybe you can change fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false) to key: "modificationDate"

By the way, I found another way:

  __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); } }]; 

can get a new PHAsset.

0
source

I updated the answer to include the return of any type of asset, as well as a simpler / clearer way to return the asset.

There is no need for a competition handler.

 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 } 
0
source

Source: https://habr.com/ru/post/1257686/


All Articles