【问题标题】:NSURL from PHAsset来自 PHAsset 的 NSURL
【发布时间】:2014-11-19 10:53:12
【问题描述】:

我正在将我们的应用程序转换为使用 iOS8 的照片框架,ALAsset 框架显然是 iOS8 下的二等公民。

我有一个问题是我们的架构确实需要一个 NSURL 来表示媒体在“磁盘”上的位置。我们使用它来将媒体上传到我们的服务器以进行进一步处理。

使用 ALAsset 很容易:

    ALAssetRepresentation *rep = [asset defaultRepresentation];
    self.originalVideo = rep.url;

但我只是没有在 PHAsset 中看到这种能力。我想我可以打电话:

    imageManager.requestImageDataForAsset

然后将其写入文件系统中的临时点,但这看起来非常繁重和浪费,更不用说可能很慢。

有没有办法得到这个,还是我要重构我的应用程序,只在 iOS7 上使用 NSURL,在 iOS8 上使用其他方法?

【问题讨论】:

  • 再看我的代码,我使用 URL 的唯一原因是将它提供给 AVAssetExportSession 和/或 AVAssetImageGenerator 所以我想我会替换那些调用。再说一次,一旦我把它提供给那些我仍然需要一个 NSURL 来传递给我们的上传者,所以我敢打赌这个问题仍然存在。
  • 从您在这里的评论看来您已经为自己弄清楚了,但其他人可以在这里看到:如果您只需要使用旧方法的 URL(如 AVAssetExportSession),您可能可以使用它们的较新版本匹配 PHAsset 而不是 AVAsset (AVURLAsset)。例如:PHImageManager.defaultManager()的requestExportSessionForVideo和requestPlayerItemForVideo

标签: ios8 alassetslibrary photosframework phasset


【解决方案1】:

如果您使用 [imageManagerrequestAVAssetForVideo...],它将返回一个 AVAsset。那个 AVAsset 实际上是一个AVURLAsset,所以如果你转换它,你可以访问它的 -url 属性。

我不确定您是否可以从中创建新资产,但它确实为您提供了位置。

【讨论】:

  • 你又来了! :-) 我忘记了这个问题。我走了一条不同的路,看看我的另一个问题,但这显然也是正确的。顺便说一句,你不是在 80 年代为柯达工作的吗?那时候认识一个jlw...
  • 可能是个愚蠢的问题,但这对图像和视频都有效吗?
  • 这不适用于慢动作视频,它将返回超类为 AVAsset 的 AVCompostion。 AVAsset 有 AVURLAsset 和 AVAsset 等子类。
  • @rishu1992 对于慢动作视频,获取 AVComposition 的 AVCompositionTrack(媒体类型为 AVMediaTypeVideo),获取其第一个片段(类型为 AVCompositionTrackSegment),然后访问其 sourceURL 属性。
  • @rishu1992 这不适用于图像,它返回一个 nil AVAsset
【解决方案2】:

SWIFT 2.0 版本 此函数从 PHAsset(图像和视频)返回 NSURL

func getAssetUrl(mPhasset : PHAsset, completionHandler : ((responseURL : NSURL?) -> Void)){

    if mPhasset.mediaType == .Image {
        let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
        options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
            return true
        }
        mPhasset.requestContentEditingInputWithOptions(options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [NSObject : AnyObject]) -> Void in
            completionHandler(responseURL : contentEditingInput!.fullSizeImageURL)
        })
    } else if mPhasset.mediaType == .Video {
        let options: PHVideoRequestOptions = PHVideoRequestOptions()
        options.version = .Original
        PHImageManager.defaultManager().requestAVAssetForVideo(mPhasset, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [NSObject : AnyObject]?) -> Void in

            if let urlAsset = asset as? AVURLAsset {
                let localVideoUrl : NSURL = urlAsset.URL
                completionHandler(responseURL : localVideoUrl)
            } else {
                completionHandler(responseURL : nil)
            }
        })
    }

}

【讨论】:

  • 如何读取路径的内容?似乎当我尝试使用 NSData(contentsOfFile: "...") 获取时,它不会被获取。有没有办法从路径中读取此文件,例如“file:///var/mobile/Media/PhotoData/PhotoCloudSharingData/211607360/28D50A9E-57E3-4280-B75D-7DC228A19147/100CLOUD/IMG_1170.JPG”
  • var path: String = pathURL.path() var data: NSData = NSFileManager.defaultManager().contentsAtPath(path)
  • 我好像没有访问权限或其他东西(已授予访问照片库的权限)。当我尝试 NSFileManager.defaultManager().fileExistsAtPath() 它返回 false 所以我也无法获取文件的内容。但该文件肯定存在。
  • 这个问题还没解决真是太疯狂了。我需要一个具有永久读取访问权限的可靠 url 用于 NSURLSessionUploadTask 工作。由于 iPhone 的存储空间非常有限,我无法将所有资产复制到临时位置以进行上传。用户的错误消息是什么样的:“很抱歉,您无法将文件上传到我们的服务器,因为您设备上的存储空间太低???”没有人会理解这一点
  • 如果您使用的是 Objective-C 而不是 Swift,请参阅 Sahil 的回答。它适用于我的普通图像。
【解决方案3】:

如果您有 PHAsset,您可以像这样获取所述资产的 url:

[asset requestContentEditingInputWithOptions:editOptions
                           completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
    NSURL *imageURL = contentEditingInput.fullSizeImageURL;
}];

【讨论】:

    【解决方案4】:

    使用 PHObject 的新 localIdentifier 属性。 (PHAsset 继承自此)。

    它提供了与 ALAsset URL 类似的功能,即您可以通过调用方法来加载资产

    +[PHAsset fetchAssetsWithLocalIdentifiers:identifiers options:options]
    

    【讨论】:

      【解决方案5】:

      上述所有解决方案都不适用于慢动作视频。我发现处理所有视频资产类型的解决方案是这样的:

      func createFileURLFromVideoPHAsset(asset: PHAsset, destinationURL: NSURL) {
          PHCachingImageManager().requestAVAssetForVideo(self, options: nil) { avAsset, _, _ in
              let exportSession = AVAssetExportSession(asset: avAsset!, presetName: AVAssetExportPresetHighestQuality)!
              exportSession.outputFileType = AVFileTypeMPEG4
              exportSession.outputURL = destinationURL
      
              exportSession.exportAsynchronouslyWithCompletionHandler {
                  guard exportSession.error == nil else {
                      log.error("Error exporting video asset: \(exportSession.error)")
                      return
                  }
      
                  // It worked! You can find your file at: destinationURL
              }
          }
      }
      

      【讨论】:

        【解决方案6】:

        看到这个答案here

        还有这个here

        根据我的经验,您需要先将资产导出到磁盘才能获得完全可访问/可靠的 URL。

        上面链接的答案描述了如何做到这一点。

        【讨论】:

          【解决方案7】:

          只想从@jlw 的评论中发布隐藏的宝石

          @rishu1992 对于慢动作视频,获取 AVComposition 的 AVCompositionTrack(mediaType AVMediaTypeVideo),抢它的第一个 段(类型为 AVCompositionTrackSegment),然后访问其 sourceURL 属性。 – jlw 2015 年 8 月 25 日 11:52

          【讨论】:

            【解决方案8】:

            谈到PHAsset 的url,我曾经在Swift 2 上准备了一个util func(虽然只用于播放来自PHAsset 的视频)。在这个答案中分享它,可能会对某人有所帮助。

            static func playVideo (view:UIViewController, asset:PHAsset)
            

            请查看Answer

            【讨论】:

              【解决方案9】:

              这是一个方便的 PHAsset 类别:

              @implementation PHAsset (Utils)
              
              - (NSURL *)fileURL {
                  __block NSURL *url = nil;
              
                  switch (self.mediaType) {
                      case PHAssetMediaTypeImage: {
                          PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
                          options.synchronous = YES;
                          [PHImageManager.defaultManager requestImageDataForAsset:self
                                                                          options:options
                                                                    resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
                                                                        url = info[@"PHImageFileURLKey"];
                                                                    }];
                          break;
                      }
                      case PHAssetMediaTypeVideo: {
                          dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
                          [PHImageManager.defaultManager requestAVAssetForVideo:self
                                                                        options:nil
                                                                  resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
                                                                      if ([asset isKindOfClass:AVURLAsset.class]) {
                                                                          url = [(AVURLAsset *)asset URL];
                                                                      }
                                                                      dispatch_semaphore_signal(semaphore);
                                                                  }];
                          dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
                          break;
                      }
                      default:
                          break;
                  }
                  return url;
              }
              
              @end
              

              【讨论】:

                【解决方案10】:

                我对视频文件有类似的问题,对我有用的是:

                NSString* assetID = [asset.localIdentifier substringToIndex:(asset.localIdentifier.length - 7)];
                NSURL* videoURL = [NSURL URLWithString:[NSString stringWithFormat:@"assets-library://asset/asset.mov?id=%@&ext=mov", assetID]];
                

                其中资产是 PHAsset。

                【讨论】:

                  猜你喜欢
                  • 2016-12-18
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-11-25
                  • 2014-05-13
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-09-14
                  相关资源
                  最近更新 更多