Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the location of a PHAsset in Swift

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?

like image 499
Linus Unnebäck Avatar asked Aug 30 '14 11:08

Linus Unnebäck


2 Answers

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.

like image 188
Linus Unnebäck Avatar answered Nov 20 '22 12:11

Linus Unnebäck


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.
            }
        }
    }
}
like image 1
guido Avatar answered Nov 20 '22 12:11

guido