【问题标题】:How to get an ALAsset URL from a PHAsset?如何从 PHAsset 获取 ALAsset URL?
【发布时间】:2015-03-05 21:02:22
【问题描述】:

您可以使用 undocumented PHAsset.ALAssetURL 属性偷偷摸摸地做到这一点,但我正在寻找记录在案的内容。


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

@interface PHAsset (Sneaky)

@property (nonatomic, readonly) NSURL *ALAssetURL;

@end

【问题讨论】:

    标签: ios8 alassetslibrary alasset photokit phasset


    【解决方案1】:

    利用PHAsset 的本地标识符创建assetURL。 例子: 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 更改扩展名 JPGrequestImageDataForAsset 返回 UTI),但在我的测试中,assetURL 的扩展名似乎无论如何都被忽略了。

    【讨论】:

    • 未记录,我看到 GUID 字符串是相同的,这很有意义,因为 PhotoKit 和 AssetsLibrary 都使用相同的 CoreData 对象 - 所以这只是 coredata 对象的 UUID .与使用私有 API 调用相比,我更喜欢这种方法。
    • 我们为了得到一个 URL 就必须做这些事太荒谬了。
    • 确保从 localIdentifier 中删除“/L0/001”,否则每次都会失败。
    • 从 localIdentifier 获取 GUID 的正确方法是拆分第一个 /。 (一些 GUID 的长度超过 32 个字符。)如果有人知道获取资产 URL 的更好方法,请在此处发布。这是 hacky 并且很容易在未来的更新中中断。
    • 不要使用这种方法。它是 hack 和无证的,Apple 可能随时更改编写资产 URL 的规则。此外,您无法处理一些边缘情况,例如未下载的资源。我之前尝试过,然后一些用户报告说他们看不到相册中的某些图像。我在我的崩溃报告中看到很多错误报告说 AssetsLibrary 在 URL:assets-library://xxx 找不到图像,花了我很多时间来弄清楚。更好的方法是将 PHAsset 提取到本地文件系统并重构您的代码以使用文件系统 URL,或者只是迁移到 PHAsset。
    【解决方案2】:

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

    【讨论】:

    • 你所说的可能是真的,但它似乎只与实际(我认为,明确说明)的问题间接相关。
    • @Clay Bridges 是的。我想我意识到帮助我解决了我的问题,并在不重新检查问题的情况下添加了答案。对不起。
    • 我发现创建一个单独的自我回答问题对于您做出的任何此类认识都是一种更好的格式。我已经做了很多,尽管他们告诉你,还没有失明。 :) 你甚至可以链接到这个问题。
    【解决方案3】:

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

    【讨论】:

    • 有没有办法获取视频网址
    【解决方案4】:

    阅读底部!

    PHImageManager.requestImageresultHandler 返回 2 个对象:resultinfo

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

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

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

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 请举例说明。
      猜你喜欢
      • 1970-01-01
      • 2016-02-24
      • 1970-01-01
      • 1970-01-01
      • 2016-11-06
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2019-02-13
      相关资源
      最近更新 更多