6

我正在使用 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]);
        });
    });
}

调试器将停止

self.moments = [PHAssetCollection fetchMomentsWithOptions:options];

出现错误:

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

这看起来很奇怪,因为我可以用orNSPredicate来过滤。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]);
        });
    });
}

调试器再次停在

self.moments = [PHAssetCollection fetchMomentsWithOptions:options];

带有不同的错误消息:

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

最后,我记得在CloudKit 文档中看到他们添加了对按距离过滤的新支持。然而,这是为了CKQuery,不是NSPredicate。无论如何,我决定试一试。我使用我的坐标进行CLLocationthen 调用:

-(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]);
        });
    });
}

你猜对了。错误:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CLLocation rangeOfString:]: unrecognized selector sent to instance 0x19e3e350'

同时,我将遍历列表PHAssetCollections并手动计算它是否在CLLocation. 这将大大降低效率。

4

1 回答 1

0

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

SELF
localIdentifier
localizedTitle (or title)
startDate
endDate
estimatedAssetCount

如果要过滤 PHCollection(而不是 PHAssetCollection),则仅限于以下键:

SELF
localIdentifier
localizedTitle (or title)
startDate
endDate

没有类似“approximateLocation”的东西是支持键。可是等等! 本地化标题通常是一个地名。别的没见过。因此,您也许可以通过谓词过滤时刻集合来获取资产

于 2017-12-04T16:02:08.037 回答