Używam frameworku Zdjęcia (aka PhotoKit
). W mojej aplikacji muszę zbierać momenty (które są typu PHAssetCollection
). PHAssetCollection
ma właściwość CLLocation *approximateLocation
.Filtruj PHAssetKolekcje w promieniu CLLocationCoordinate2d
Jednak nie mogę uzyskać NSPredicate
do pracy po odzyskaniu momentów z PhotoKit.
-(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]);
});
});
}
Debuger zatrzyma na
self.moments = [PHAssetCollection fetchMomentsWithOptions:options];
z błędem:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unsupported predicate in fetch options: approximateLocation.coordinate.latitude < 37'
To wydaje się dziwne, ponieważ mogę używać NSPredicate
filtrować przez startDate
lub endDate
.
Zresztą obok pomyślałem, że spróbować NSPredicate
z bloku:
-(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]);
});
});
}
Ponownie debugger zatrzymuje się
self.moments = [PHAssetCollection fetchMomentsWithOptions:options];
z innym komunikatem o błędzie:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unsupported predicate in fetch options: BLOCKPREDICATE(0x27d338)'
W końcu przypomniałem sobie, że przeczytałem w CloudKit documentation, że dodali nowe wsparcie dla fil tering według odległości. Jednak jest to dla CKQuery
, a nie NSPredicate
. Postanowiłem jakoś spróbować. Używam koordynować zrobić CLLocation
następnie zadzwonić:
-(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]);
});
});
}
Zgadłeś. Błąd:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CLLocation rangeOfString:]: unrecognized selector sent to instance 0x19e3e350'
W tym czasie ja po prostu iterację listy PHAssetCollections
i ręcznie obliczyć, czy to w pobliżu CLLocation
. Będzie to znacznie mniej wydajne.
Czy zdarzyło Ci się, że to działa? –
Nie. Nie zawarłem zbyt wiele kodu od czasu pierwotnego wpisu. Opublikuj ponownie, jeśli działa. Może działa na iOS 10? – VaporwareWolf