【问题标题】:iOS8 Photos Framework: How to get the name(or filename) of a PHAsset?iOS8 照片框架:如何获取 PHAsset 的名称(或文件名)?
【发布时间】:2015-03-07 10:36:27
【问题描述】:

我正在尝试使用PHAssets 获取图像名称。但我找不到文件名的元数据或任何获取图像名称的方法。有没有其他方法来获取文件名?

【问题讨论】:

    标签: ios phasset


    【解决方案1】:

    我知道这个问题已经得到解答,但我想我会提供另一种选择:

    extension PHAsset {
    
        var originalFilename: String? {
    
            var fname:String?
    
            if #available(iOS 9.0, *) {
                let resources = PHAssetResource.assetResources(for: self)
                if let resource = resources.first {
                    fname = resource.originalFilename
                }
            }
    
            if fname == nil {
                // this is an undocumented workaround that works as of iOS 9.1
                fname = self.value(forKey: "filename") as? String
            }
    
            return fname
        }
    }
    

    【讨论】:

    • 请注意,PHAssetResource 仅适用于 iOS 9+。
    • 我尝试将您的代码与使用“originalFilename”作为键的排序描述符一起使用,它给出了“获取选项中不支持的排序描述符”错误。
    【解决方案2】:

    如果你想获得像IMG_XXX.JPG这样的图片名称(例如照片中最后一张照片的名称),你可以试试这个:

    PHAsset *asset = nil;
    PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
    fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
    PHFetchResult *fetchResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions];
    if (fetchResult != nil && fetchResult.count > 0) {
        // get last photo from Photos
        asset = [fetchResult lastObject];
    }
    
    if (asset) {
        // get photo info from this asset
        PHImageRequestOptions * imageRequestOptions = [[PHImageRequestOptions alloc] init];
        imageRequestOptions.synchronous = YES;
        [[PHImageManager defaultManager]
                 requestImageDataForAsset:asset
                                options:imageRequestOptions
                          resultHandler:^(NSData *imageData, NSString *dataUTI,
                                          UIImageOrientation orientation, 
                                          NSDictionary *info) 
         {
              NSLog(@"info = %@", info);
              if ([info objectForKey:@"PHImageFileURLKey"]) {
                   // path looks like this - 
                   // file:///var/mobile/Media/DCIM/###APPLE/IMG_####.JPG
                   NSURL *path = [info objectForKey:@"PHImageFileURLKey"];
         }                                            
        }];
    }
    

    希望对你有帮助。

    在 Swift 中,代码如下所示

    PHImageManager.defaultManager().requestImageDataForAsset(asset, options: PHImageRequestOptions(), resultHandler:
    {
        (imagedata, dataUTI, orientation, info) in
        if info!.keys.contains(NSString(string: "PHImageFileURLKey"))
        {
            let path = info![NSString(string: "PHImageFileURLKey")] as! NSURL
        }
    })
    

    斯威夫特 4

        let fetchResult = PHAsset.fetchAssets(with: .image, options: nil)
        if fetchResult.count > 0 {
            if let asset = fetchResult.firstObject {
                let date = asset.creationDate ?? Date()
                print("Creation date: \(date)")
                PHImageManager.default().requestImageData(for: asset, options: PHImageRequestOptions(),
                    resultHandler: { (imagedata, dataUTI, orientation, info) in
                        if let info = info {
                            if info.keys.contains(NSString(string: "PHImageFileURLKey")) {
                                if let path = info[NSString(string: "PHImageFileURLKey")] as? NSURL {
                                    print(path)
                                }
                            }
                        }
                })
            }
        }
    

    【讨论】:

    • 这只是肮脏的解决方法。 PHImageFileURLKey 是未记录的键,如果编辑图像(例如使用图像过滤器),此 URL 在最后一个路径组件中没有唯一名称。
    • 绒毛会一直是 file:///var/mobile/Media/DCIM/###APPLE/IMG_####.JPG 吗?有什么方法可以加密并获取文件名,例如 test.png?
    • 还有什么方法可以阻止系统重命名图像?如果我将图像传输到我的设备,我希望它保持它们在我的计算机上的相同文件名,我从中传输它们然后将它们导入应用程序。是这样吗?
    • 在信息更新答案下此名称中没有键
    • @wanttobeprofessional 请查看更新后的答案。您可以在asset.creationDate 属性中找到一个日期,然后使用 (NS)DateFormatter 对其进行格式化。
    【解决方案3】:

    另一种选择是:

    [asset valueForKey:@"filename"]
    

    这件事的“合法性”由你来决定。

    【讨论】:

    • PHAsset 没有名为“文件名”的属性。它是如何工作的?
    • 魔术。 =] 它是私有属性,未在公共 API 中公开。它相对比较好用,因为还有其他公共 API 属性称为 filename
    • @CaseyHancock 我想是的。从发布答案的时间来看,它很可能在 iOS 8 上进行了测试。请务必进行测试以确定。
    【解决方案4】:

    Swift 4 中 iOS 9+ 最简单的解决方案(基于略读答案):

    extension PHAsset {
        var originalFilename: String? {
            return PHAssetResource.assetResources(for: self).first?.originalFilename
        }
    }
    

    【讨论】:

    • 太棒了,谢谢!我有没有提到,我喜欢 Swift 做这些事情? ;)
    • 这将给出原始文件名.. 但不是 CameraRoll 为文件提供的新名称。
    • 谢谢!这是最短的方法。
    【解决方案5】:

    对于斯威夫特

    asset?.value(forKey: "filename") as? String
    

    对于目标 C

    [asset valueForKey:@"filename"]
    

    【讨论】:

      【解决方案6】:

      当您有资产的引用 url 时使用 Swift 的最简单答案:

      if let asset = PHAsset.fetchAssetsWithALAssetURLs([referenceUrl], options: nil).firstObject as? PHAsset {
      
          PHImageManager.defaultManager().requestImageDataForAsset(asset, options: nil, resultHandler: { _, _, _, info in
      
              if let fileName = (info?["PHImageFileURLKey"] as? NSURL)?.lastPathComponent {      
                  //do sth with file name
              }
          })
      }
      

      【讨论】:

        【解决方案7】:

        SWIFT4: 第一个import Photos

        if let asset = PHAsset.fetchAssets(withALAssetURLs: [info[UIImagePickerControllerReferenceURL] as! URL],
                                                   options: nil).firstObject {
        
        
                    PHImageManager.default().requestImageData(for: asset, options: nil, resultHandler: { _, _, _, info in
        
                        if let fileName = (info?["PHImageFileURLKey"] as? NSURL)?.lastPathComponent {
                            print("///////" + fileName + "////////")
                            //do sth with file name
                        }
                    })
                }
        

        【讨论】:

          【解决方案8】:

          您真正要寻找的是 localIdentifier,它是一个唯一的字符串,可以持续标识对象。

          使用此字符串通过以下方式查找对象:

          fetchAssetsWithLocalIdentifiers:options:, fetchAssetCollectionsWithLocalIdentifiers:options:, or fetchCollectionListsWithLocalIdentifiers:options: method.

          更多信息请见here

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-12-17
            • 2012-04-04
            • 1970-01-01
            相关资源
            最近更新 更多