Фильтровать PHAssetCollections в радиусе CLLocationCoordinate2d
Я использую рамки для фотографий (иначе PhotoKit
). В моем приложении мне нужно собрать моменты (которые имеют тип PHAssetCollection
). PHAssetCollection
имеет свойство CLLocation *approximateLocation
,
Однако я не могу получить NSPredicate
работать, когда я получаю Моменты из 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]);
});
});
}
Отладчик остановится на
self.moments = [PHAssetCollection fetchMomentsWithOptions:options];
с ошибкой:
*** Завершение работы приложения из-за невыполненного исключения "NSInvalidArgumentException", причина: "Неподдерживаемый предикат в параметрах выборки: ApproxateLocation.coordinate.latitude < 37".
Это кажется странным, так как я могу использовать NSPredicate
фильтровать по startDate
или же endDate
,
Во всяком случае, в следующий раз я решил попробовать NSPredicate
с блоком:
-(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
, Я все равно решил попробовать. Я использую свою координату, чтобы сделать 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]);
});
});
}
Ты угадал. Ошибка:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CLLocation rangeOfString:]: unrecognized selector sent to instance 0x19e3e350'
А пока я просто переберу список PHAssetCollections
и вручную рассчитать, если он находится рядом с CLLocation
, Это будет гораздо менее эффективно.
1 ответ
Если вы посмотрите на Таблицу 1 документации PHFetchOptions, вы увидите, что вы можете использовать только следующие ключи для фильтрации предикатов PHAssetCollections:
SELF
localIdentifier
localizedTitle (or title)
startDate
endDate
estimatedAssetCount
если вы хотите отфильтровать PHCollection (в отличие от PHAssetCollection), вы ограничены следующими ключами:
SELF
localIdentifier
localizedTitle (or title)
startDate
endDate
Ничто, напоминающее "приблизительное местоположение", не является ключом поддержки. Но ждать! LocalizedTitle - это, как правило, название места. Не видел это иначе. Таким образом, вы можете получить активы с помощью предиката, фильтрующего коллекции моментов.