elmir
elmir

Reputation: 97

How to Fetch PHAssets that only have location data

In the Photos framework for iOS, in order to make a request for a set of PHAssets with specific filters, you use the fetchAssetsWithOptions:options and pass a PHFetchOptions object with the filters wanted.

I'm trying to filter out any PHAssets that don't have a location asset metadata object in them, and not entirely sure if it can be done with the predicate option on the PHFetchOptions. There might be another way to filter out the assets based on if location is present, but I'm not entirely sure on the most efficient way to do this.

//Photos fetch
PHFetchOptions *options = [[PHFetchOptions alloc] init];

options = [NSPredicate predicateWithFormat:@"mediaType == %d", PHAssetMediaTypeImage];
options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];

PHFetchResult *assetsFetchResults = [PHAsset fetchAssetsWithOptions:options];

Upvotes: 2

Views: 2067

Answers (1)

holtmann
holtmann

Reputation: 6293

According to the documentation at https://developer.apple.com/library/prerelease/ios/documentation/Photos/Reference/PHFetchOptions_Class/index.html this can't be done using a predicate. The location property of PHAsset can't be used in a predicate/sortDescriptor.

So the only option is to enumerate through the objects of the PHFetchResult and then filter out the ones that do not have location data. This is of course slower than using a predicate but might be still a solution depending on your use case.

Example for using this approach:

[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
    PHFetchResult *result = [PHAsset fetchAssetsWithOptions:nil];
    NSMutableArray *filteredAssets = [NSMutableArray new];
    [result enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL * _Nonnull stop) {
        if (asset.location != nil) {
            [filteredAssets addObject:asset];
        }
    }];

    //optional - create new Collection/fetchresult with filtered assets
    PHAssetCollection *assetCollectionWithLocation = [PHAssetCollection transientAssetCollectionWithAssets:filteredAssets title:@"Assets with location data"];
    PHFetchResult *filteredResult = [PHAsset fetchAssetsInAssetCollection:assetCollectionWithLocation options:nil];

}];

Upvotes: 11

Related Questions