For some reason the location
property on a PHAsset
is only exposed in Objective-c and not in Swift.
Documentation: PHAsset.location
To work around it, I figured I could create a Objective-C class whose sole purpose is to extract the location and import it into Swift.
LocationGetter.h
@interface LocationGetter : NSObject
+ (CLLocation *)locationForAsset:(PHAsset *) asset;
@end
LocationGetter.m
@implementation LocationGetter
+ (CLLocation *)locationForAsset:(PHAsset *) asset {
return [asset location];
}
@end
So far so good, but when I try to use it in Swift:
LocationGetter.locationForAsset(ass)
'LocationGetter.Type' does not have a member named 'locationForAsset'
Bonus question: Why on earth didn't Apple expose location
in swift?
It turns out that the answer is really simple. The problem is that the Swift file don't know what a CLLocation
is, and thus refuses to import that function. Importing CoreLocation
solves the issue.
import CoreLocation
LocationGetter.locationForAsset(ass)
EDIT: Apple has since included .location
as a getter on the PHAsset
. Getting the location is now as easy as asset.location
.
For those who looking to print each photo location, here it is:
var allAssets = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: nil)
allAssets.enumerateObjectsUsingBlock({asset, index, stop in
if let ass = asset as? PHAsset{
println(ass.location)
}
}
You can retrieve the location of every PHAsset
as easy as these lines of code:
let phFetchRes = PHAsset.fetchAssets(with: PHAssetMediaType.image , options: nil) // Fetch all PHAssets of images from Camera roll
let asset = phFetchRes.object(at: 0) // retrieve cell 0 as a asset
let location = asset.location // retrieve the location
print(location) // Print result
Or if you want to retrieve all of locations from PHAsset you can use above codes like this:
let phFetchRes = PHAsset.fetchAssets(with: PHAssetMediaType.image , options: nil) // Fetch all PHAssets of images from Camera roll
phFetchRes.enumerateObjectsUsingBlock({asset, index, stop in
if let ass = asset as? PHAsset{
println(ass.location)
}
}
iOS12, Swift 4 - Get location from Photo Library Moment, if asset itself does not have location.
I noticed that sometimes, the location of the asset itself was nil, while, in the Photo's app, the asset was grouped into a moment that had a location. If I had to guess, I'd say the photo app groups photos by date into a moment and then if at least one of those photos has a location, the moment is given a location.
Now, how to get the location of that moment, if the location of the asset itself is nil? Like this:
if let asset = info[UIImagePickerController.InfoKey.phAsset] as? PHAsset {
if let photoCoordinate = asset.location?.coordinate {
// The asset itself has a location. Do something with it.
}
else {
// The asset itself does not have a location
// find the moments containing the asset
let momentsContainingAsset = PHAssetCollection.fetchAssetCollectionsContaining(asset, with: .moment, options: nil)
for i in 0..<momentsContainingAsset.count {
let moment = momentsContainingAsset.object(at: i)
if let momentCoordinate = moment.approximateLocation?.coordinate {
// this moment has a location. Use it as you wish.
}
}
}
}