Getting the location of a PHAsset in Swift

2019-06-18 22:46发布

问题:

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?

回答1:

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.



回答2:

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)
        }
    }


回答3:

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)
    }
}


回答4:

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.
            }
        }
    }
}