【发布时间】:2020-06-17 16:02:02
【问题描述】:
我正在尝试从UIImagePickerController 提供的PHAsset 参考中获取文件名,从库中选择并用相机拍照时如何检索图像文件名?
我正在使用 Xcode 11.4 和 Swift 5。
【问题讨论】:
标签: swift uiimagepickercontroller phasset
我正在尝试从UIImagePickerController 提供的PHAsset 参考中获取文件名,从库中选择并用相机拍照时如何检索图像文件名?
我正在使用 Xcode 11.4 和 Swift 5。
【问题讨论】:
标签: swift uiimagepickercontroller phasset
鉴于您已经拥有 PHAsset 对象,PHAssetResource 是您检索文件名所需要的。
let assetResources = PHAssetResource.assetResources(for: asset)
这将为您返回一组PHAssetResource 实例,其中一个是当前图像。
在调试器上检查 PHAssetResource 实例,您可以看到它包含多个文件。这可能包括由 .plist 表示的调整数据以及一张或多张照片。
要获取当前可访问的文件,您需要查找的是密钥isCurrent。 Apple 没有将此键作为 PHAssetResource 的变量公开,但是,他们没有采取任何努力隐藏该值。我假设,查询这个值不会导致应用被拒绝。
您可以直接查询该值,也可以通过扩展 PHAssetResource 来更简洁地查询。
extension PHAssetResource {
var isCurrent: Bool? {
self.value(forKey: "isCurrent") as? Bool
}
}
现在,您可以向[PHAssetResource] 询问isCurrent 的第一个项目以及照片或视频。
let resourceTypes: [PHAssetResourceType] = [.photo, .video, .audio, .fullSizePhoto]
let currentAssetResource = assetResources.first(
where: { $0.isCurrent == true && resourceTypes.contains($0.type)
})
最后是文件名。
let fileName = currentAssetResource?.originalFilename
注意
PhotoKit 期望开发人员使用抽象资产资源,而不是处理底层文件或数据。似乎允许使用isCurrent。但是,可以通过 iOS 更新更改或删除该值。仅当您有提取文件名的强大用例时才这样做。
【讨论】:
有两种方法:
您可以使用info[.imageURL] 检索UIImagePickerController 为您创建的临时文件的URL。如果您只需要例如资产的扩展,这就足够了。
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
// url of temporary file provided by image picker
if let url = info[.imageURL] as? URL {
print("temp URL", url) // file:///private/var/mobile/Containers/Data/Application/.../tmp/FAC0D82B-85A9-4C7A-B69C-58BB53F74CDC.jpeg
}
dismiss(animated: true)
}
但文件名本身与原始资产无关。
您可以从 Photos 框架中检索原始资产 URL。我们以前可以使用PHImageManager,调用requestImageDataForAsset,然后在生成的信息字典中使用"PHImageFileURLKey",但现在不行了。
但作为suggested elsewhere,您可以asset.requestContentEditingInput,其中包括资产的URL:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
// url of the original asset
if let asset = info[.phAsset] as? PHAsset {
asset.requestContentEditingInput(with: nil) { input, info in
if let fileURL = input?.fullSizeImageURL {
print("original URL", fileURL) // file:///var/mobile/Media/DCIM/100APPLE/IMG_0135.HEIC
}
}
}
dismiss(animated: true)
}
如果你这样做,你显然需要请求照片库的权限,特别是:
if PHPhotoLibrary.authorizationStatus() == .notDetermined {
PHPhotoLibrary.requestAuthorization { granted in
print(granted)
}
}
您需要在您的Info.plist 中提供一个NSPhotoLibraryUsageDescription 用法字符串。
就个人而言,当您真的不需要编辑时请求内容编辑输入感觉是错误的,但是 AFAIK,这是目前获得原始资产名称的唯一方法。 (一定有更好的方法:如果您在调试器中浏览 PHAsset,资产名称实际上是埋在那里,但没有暴露出来......也许他们这样做是为了避免与 HEIC 扩展名混淆。)
归根结底,这取决于您需要的名称。如果您只需要临时文件的路径,请使用.imageURL。如果您需要有关原始资产的信息,请使用 .phAsset 和 Photos/PhotoKit 框架。
【讨论】: