Reputation: 491
I have noticed when the photo picker is presented, at the bottom it shows "Location Is Included", and the Options menu allows the user to turn that off.
How can we check if CLLocation or Captions as per the inclusion from the options menu are provided when getting the photo from:
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?
}
}
Is the only way to access metadata / gps info? WITHOUT having to access a PHAsset by requesting permission?
Upvotes: 2
Views: 84
Reputation: 275125
From this answer, all you need to do is
PhotosPickerItem
as Data
CGImageSource
from the dataCGImageSource
So
@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
}
}
The location info and caption are all somewhere in the metadata dictionary. The keys of the dictionaries are all listed in the subsections here.
The location information stored under the kCGImagePropertyGPSDictionary
key, which is itself another dictionary. There are different keys for the latitude, longitude, altitude, speed, and so on.
Here I wrote a function that gets the location as a 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
)
}
I've found two places where the caption is stored.
kCGImagePropertyTIFFDictionary
key, then the kCGImagePropertyTIFFImageDescription
key of that dictionary.kCGImagePropertyIPTCDictionary
key. then the kCGImagePropertyIPTCCaptionAbstract
key of that dictionary.Upvotes: 0