6

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?

Shruti Thombre
  • 989
  • 4
  • 11
  • 27
Linus Unnebäck
  • 23,234
  • 15
  • 74
  • 89
  • Can you share more code please? For some reason this crashes for me. Not all of my assets have a location, maybe that is the reason, but I don't know how to handle this in objective c function you provided, help would be much appreciated. – alexsalo Dec 27 '14 at 20:11
  • @alexsalo It seems like Apple have fixed the `location` accessor in Swift. You should be able to just do `ass.location` to get the location. `ass` is your PHAsset. [Documentation: PHAsset.location](https://developer.apple.com/library/prerelease/ios/documentation/Photos/Reference/PHAsset_Class/index.html#//apple_ref/occ/instp/PHAsset/location) – Linus Unnebäck Dec 27 '14 at 20:33
  • Yes, you are quite right, I had an issue with unwrapping then. Thanks again! – alexsalo Dec 28 '14 at 03:11

4 Answers4

5

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.

Linus Unnebäck
  • 23,234
  • 15
  • 74
  • 89
1

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.
            }
        }
    }
}
guido
  • 2,792
  • 1
  • 21
  • 40
0

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)
        }
    }
alexsalo
  • 1,406
  • 2
  • 14
  • 16
0

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)
    }
}
Mamad Farrahi
  • 394
  • 1
  • 5
  • 20