我注意到,当显示照片选择器时,底部会显示“包含位置”,并且“选项”菜单允许用户将其关闭。
我们如何检查从以下位置获取照片时是否提供了选项菜单中包含的 CLLocation 或标题:
PhotosPicker(selection: $selectedItem, matching: .images, photoLibrary: .shared()) {
Text("Open Photo Picker")
}
.onChange(of: selectedItem) { newItem in
if let selected = newItem {
// Have PhotosPickerItem, now how to get CLLocation?
}
}
这是访问元数据/GPS 信息的唯一方法吗? 无需通过请求许可来访问 PHAsset?
从这个答案,您需要做的就是
PhotosPickerItem
加载为 Data
CGImageSource
CGImageSource
所以
@State var selection: PhotosPickerItem?
var body: some View {
PhotosPicker("Pick", selection: $selection)
.task(id: selection) {
guard let data = try? await selection?.loadTransferable(type: Data.self),
let src = CGImageSourceCreateWithData(data as CFData, nil),
let metadata = CGImageSourceCopyPropertiesAtIndex(src,0,nil) else {
return
}
print(metadata) // metadata is a CFDictionary
}
}
位置信息和标题都在元数据字典中。字典的键都在here小节中列出。
kCGImagePropertyGPSDictionary
键下存储的位置信息,它本身就是另一个字典。纬度、经度、海拔、速度等有不同的按键。
这里我编写了一个函数,以
CLLocationCoordinate2D
: 的形式获取位置
func coordinates(from metadata: CFDictionary) -> CLLocationCoordinate2D? {
guard let dict = metadata as? [AnyHashable: Any],
let gpsDict = dict[kCGImagePropertyGPSDictionary] as? [AnyHashable: Any],
let lat = gpsDict[kCGImagePropertyGPSLatitude] as? Double,
let lon = gpsDict[kCGImagePropertyGPSLongitude] as? Double,
let latRef = gpsDict[kCGImagePropertyGPSLatitudeRef] as? String,
let lonRef = gpsDict[kCGImagePropertyGPSLongitudeRef] as? String
else { return nil }
return CLLocationCoordinate2D(
latitude: latRef == "N" ? lat : -lat,
longitude: lonRef == "E" ? lon : -lon
)
}
我找到了两个存储标题的地方。
kCGImagePropertyTIFFDictionary
键,然后按该字典的 kCGImagePropertyTIFFImageDescription
键。kCGImagePropertyIPTCDictionary
键下。然后是该字典的 kCGImagePropertyIPTCCaptionAbstract
键。