Фильтровать 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 - это, как правило, название места. Не видел это иначе. Таким образом, вы можете получить активы с помощью предиката, фильтрующего коллекции моментов.

Другие вопросы по тегам