使用Photos Framework获取相机拍摄图片的URL

8
我有一个应用程序,使用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吗?

最好的, 乔治


乔治,你找到解决方案了吗?我也遇到了同样的问题,但是找不到任何解决方案... - gersonmdesouza
3个回答

5

更新:看起来我已经找到了解决这个问题的方法。

步骤1:将图像保存到相机中。

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

这是异步完成的操作,因此请确保在操作完成后设置选择器。

第二步:当操作完成时,我会执行以下操作:

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,而是一个独特的标识符,它不会更改。以此方式,您可以完美地访问保存的图像。

希望这对其他人有所帮助!


“localIdentifier”应该传入什么? - Anny
这里的localIdentifier字符串是什么,我该如何调用这个方法? - user2834653
这只是一个解决方法,而不是解决方案。如果在你保存照片并调用“fetchLastImage”之前,其他进程(例如照片同步)保存了另一张照片,会怎样呢? - Awais Fayyaz

1

我同意你的看法。

但是,如果图片的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。

0

我已更新答案,包括返回任何资产类型的方法,以及更简单/更清晰的返回资产的方式。

不需要竞争处理程序。

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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接