如何从PHAsset获取ALAsset的URL?

22

你可以使用未记录PHAsset.ALAssetURL属性进行隐秘操作,但我正在寻找一些有文档支持的方法。


† 在 Objective-C 中,这将有所帮助

@interface PHAsset (Sneaky)

@property (nonatomic, readonly) NSURL *ALAssetURL;

@end
5个回答

47
利用PHAssetlocalidentifier创建资产URL。 示例: PHAsset.localidentifier返回91B1C271-C617-49CE-A074-E391BA7F843F/L0/001 现在取前32个字符来构建assetURL,例如: assets-library://asset/asset.JPG?id=91B1C271-C617-49CE-A074-E391BA7F843F&ext=JPG 根据资产的UTI(requestImageDataForAsset返回UTI)可以更改扩展名JPG,但在我的测试中,资产URL的扩展名似乎无论如何都被忽略。

1
这是否假设PHAsset是本地资源? - Ryan Heitner
55
我们必须完成这些无聊的步骤才能获取一个URL,真是太荒谬了。 - user3344977
2
确保从localIdentifier中删除“/L0/001”,否则每次都会失败。 - user3344977
6
从localIdentifier获取GUID的正确方法是在第一个斜杠 / 处拆分。(有些GUID长度超过32个字符。)如果有人知道更好的获取资源URL的方法,请在这里发布。这种方法不够完美,将来易出问题。 - sabalaba
4
不要使用这种方法。它是一种非正式的黑客方式,苹果可能随时更改组合资源URL的规则。此外,您无法处理某些未下载的资源边缘情况。我以前尝试过,然后一些用户报告称他们无法从相册中看到某些图像。我的崩溃报告器中有很多错误报告,说AssetsLibrary找不到URL为assets-library://xxx的图像,这花费了我很多时间来解决。更好的方法是将PHAsset提取到本地文件系统并重构您的代码以使用文件系统URL,或者只需迁移到PHAsset。 - Pride Chung
显示剩余7条评论

9

我希望能够获取资产的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中。)


2
你说的可能是对的,但它似乎只与实际问题(我认为已经清楚地表述)存在些许关联。 - Clay Bridges
@Clay Bridges 确实。我想我有一个领悟,帮助我解决了我的问题,并在没有重新检查问题的情况下添加了一个答案。抱歉。 - Matt
2
我发现创建一个单独的自问自答问题是更好的格式,适用于你所做的任何这样的实现。我已经做了很多次了,尽管他们告诉你什么,但我还没有失明。 :) 你甚至可以链接到这个问题。 - Clay Bridges

2

请看下方!

PHImageManager.requestImageresultHandler 返回2个对象:resultinfo

您可以使用以下代码获取 PHAsset 的原始文件名(例如 IMG_1043.JPG)以及其在文件系统上的完整路径:

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

这应该是可以正常工作的,但由于某些原因它没有成功。所以基本上,您需要将图像复制到文件中,然后访问该文件,然后删除它。

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


2

以下是在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");
            }
        }];
    }];

有没有一种方法可以获取视频链接? - Durgaprasad

1
这是一个用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)
                }
            })
        }
    }
}

请举例说明用法。 - Chandan Jee

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