如何从 PHAsset 中获取 ALAsset URL?

How to get an ALAsset URL from a PHAsset?

您可以使用 undocumented PHAsset.ALAssetURL 属性 偷偷摸摸地完成†,但我正在寻找记录的内容。


† 在 Objective-C 中,这将有助于

@interface PHAsset (Sneaky)

@property (nonatomic, readonly) NSURL *ALAssetURL;

@end

利用 PHAsset 的本地标识符创建 assetURL。 例子: PHAsset.localidentifier returns 91B1C271-C617-49CE-A074-E391BA7F843F/L0/001

现在取前 32 个字符构建 assetURL,如:

assets-library://asset/asset.JPG?id=91B1C271-C617-49CE-A074-E391BA7F843F&ext=JPG

您可以根据资产的 UTI(requestImageDataForAsset returns UTI)更改扩展名 JPG,但在我的测试中,assetURL 的扩展名似乎被忽略了无论如何。

我也希望能够为一项资产获得 URL。但是,我已经意识到可以保留 localIdentifier 并用于恢复 PHAsset.

PHAsset* asset = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil].firstObject;

旧版资产 URL 可以使用以下方式转换:

PHAsset* legacyAsset = [PHAsset fetchAssetsWithALAssetUrls:@[assetUrl] options:nil].firstObject;
NSString* convertedIdentifier = legacyAsset.localIdentifier;

(在该方法被废弃之前...)

(感谢 holtmann - localIdentifier 隐藏在 PHObject 中。)

这是在 iOS 11 模拟器和设备

上测试的工作代码
PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];
    [result enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        PHAsset *asset = (PHAsset *)obj;
        [asset requestContentEditingInputWithOptions:nil completionHandler:^(PHContentEditingInput * _Nullable contentEditingInput, NSDictionary * _Nonnull info) {
            NSLog(@"URL:%@",  contentEditingInput.fullSizeImageURL.absoluteString);
            NSString* path = [contentEditingInput.fullSizeImageURL.absoluteString substringFromIndex:7];//screw all the crap of file://
            NSFileManager *fileManager = [NSFileManager defaultManager];
            BOOL isExist = [fileManager fileExistsAtPath:path];
            if (isExist)
                NSLog(@"oh yeah");
            else {
                NSLog(@"damn");
            }
        }];
    }];

读到底!

resultHandler for PHImageManager.requestImage returns 2 个对象:resultinfo.

您可以获得 PHAsset 的原始文件名(如 IMG_1043.JPG)及其在文件系统中的完整路径:

let url = info?["PHImageFileURLKey"] as! URL

这应该可以正常工作,但由于某些原因却不能。所以基本上,您必须将图像复制到一个文件,然后访问该文件,然后删除它。

PHImageFileURLKey 可用于获取原始文件名,但您实际上无法访问该文件。这可能与后台代码可以访问该文件而其他应用程序可以删除它有关。

这是一个用 Swift 编写的 PHAsset 扩展,它将检索 URL。

extension PHAsset {

    func getURL(completionHandler : @escaping ((_ responseURL : URL?) -> Void)){
        if self.mediaType == .image {
            let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
            options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
                return true
            }
            self.requestContentEditingInput(with: options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [AnyHashable : Any]) -> Void in
                completionHandler(contentEditingInput!.fullSizeImageURL as URL?)
            })
        } else if self.mediaType == .video {
            let options: PHVideoRequestOptions = PHVideoRequestOptions()
            options.version = .original
            PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) -> Void in
                if let urlAsset = asset as? AVURLAsset {
                    let localVideoUrl: URL = urlAsset.url as URL
                    completionHandler(localVideoUrl)
                } else {
                    completionHandler(nil)
                }
            })
        }
    }
}