过滤CLLocationCoordinate2d半径内的PHAssetCollections

Vap*_*olf 5 core-location nspredicate ios photokit ckquery

我正在使用Photos框架(又名PhotoKit).在我的应用程序中,我需要收集Moments(属于类型PHAssetCollection).PHAssetCollection有一个属性CLLocation *approximateLocation.

但是NSPredicate当我从PhotoKit检索Moments时,我无法工作.

-(void)getMomentsNearCoordinate:(CLLocationCoordinate2D)coordinate completionBlock:(PKAssetManagerArrayBlock)completionBlock{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        PHFetchOptions *options = [[PHFetchOptions alloc] init];
        options.predicate = [NSPredicate predicateWithFormat:@"approximateLocation.coordinate.latitude < 37.0"];

        self.moments = [PHAssetCollection fetchMomentsWithOptions:options];

        // Convert PHCollection into NSArray
        NSMutableArray *momentsArray = [[NSMutableArray alloc]initWithCapacity:self.moments.count];
        [self.moments enumerateObjectsUsingBlock:^(PHAssetCollection *moment, NSUInteger idx, BOOL *stop) {
            [momentsArray addObject:moment];
        }];

        dispatch_async(dispatch_get_main_queue(), ^{
            completionBlock([NSArray arrayWithArray:momentsArray]);
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

调试器将停止运行

self.moments = [PHAssetCollection fetchMomentsWithOptions:options];
Run Code Online (Sandbox Code Playgroud)

有错误:

***由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'获取选项中不支持的谓词:approximateLocation.coordinate.latitude <37'

这似乎很奇怪,因为我可以使用或NSPredicate过滤.startDateendDate

无论如何,接下来我以为我会尝试使用NSPredicatewith块:

-(void)getMomentsNearCoordinate:(CLLocationCoordinate2D)coordinate completionBlock:(PKAssetManagerArrayBlock)completionBlock{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        PHFetchOptions *options = [[PHFetchOptions alloc] init];
        options.predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
            // Logic goes here
            return YES;
        }];

        self.moments = [PHAssetCollection fetchMomentsWithOptions:options];

        // Convert PHCollection into NSArray
        NSMutableArray *momentsArray = [[NSMutableArray alloc]initWithCapacity:self.moments.count];
        [self.moments enumerateObjectsUsingBlock:^(PHAssetCollection *moment, NSUInteger idx, BOOL *stop) {
            [momentsArray addObject:moment];
        }];
        dispatch_async(dispatch_get_main_queue(), ^{
            completionBlock([NSArray arrayWithArray:momentsArray]);
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

调试器再次停止

self.moments = [PHAssetCollection fetchMomentsWithOptions:options];
Run Code Online (Sandbox Code Playgroud)

使用不同的错误消息:

***由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'获取选项中不支持的谓词:BLOCKPREDICATE(0x27d338)'

最后我记得在CloudKit文档读到他们为远程过滤添加了新的支持.然而,这是为了CKQuery,而不是NSPredicate.无论如何我决定尝试一下.我使用我的坐标进行CLLocation调用:

-(void)getMomentsNearLocation:(CLLocation*)location completionBlock:(PKAssetManagerArrayBlock)completionBlock{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        PHFetchOptions *options = [[PHFetchOptions alloc] init];
        options.predicate = [NSPredicate predicateWithFormat:@"distanceToLocation:fromLocation:(%K,%@) < %f",
                             location,
                             2.0];

        self.moments = [PHAssetCollection fetchMomentsWithOptions:options];

        // Convert PHCollection into NSArray
        NSMutableArray *momentsArray = [[NSMutableArray alloc]initWithCapacity:self.moments.count];
        [self.moments enumerateObjectsUsingBlock:^(PHAssetCollection *moment, NSUInteger idx, BOOL *stop) {
            [momentsArray addObject:moment];
        }];
        dispatch_async(dispatch_get_main_queue(), ^{
            completionBlock([NSArray arrayWithArray:momentsArray]);
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

你猜到了.错误:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CLLocation rangeOfString:]: unrecognized selector sent to instance 0x19e3e350'
Run Code Online (Sandbox Code Playgroud)

同时我只是遍历列表PHAssetCollections并手动计算它是否接近CLLocation.这样效率会低得多.

Blu*_*Med 0

如果您查看 PHFetchOptions 文档的表 1,您会发现只能使用以下键对 PHAssetCollections 进行谓词过滤:

SELF
localIdentifier
localizedTitle (or title)
startDate
endDate
estimatedAssetCount
Run Code Online (Sandbox Code Playgroud)

如果您想过滤 PHCollection(而不是 PHAssetCollection),那么您只能使用以下键:

SELF
localIdentifier
localizedTitle (or title)
startDate
endDate
Run Code Online (Sandbox Code Playgroud)

类似“approximateLocation”的东西都不是支持键。可是等等! localizedTitle 通常是地名。其他方面还没有看到过。因此,您也许可以通过谓词过滤时刻集合来获取资产