Использование NSPredicate в 2D-массивах - PullRequest
2 голосов
/ 30 декабря 2010

Этот вопрос основан на том же приложении / источнике из моего предыдущего вопроса, который можно найти здесь:

Как управлять памятью с помощью классов в Objective-C?

У меня есть вложенный массив, который при распечатке выглядит примерно так (я скопировал и вставил только небольшую его часть).

(
        (
        <Term: 0x4256420>,
        <Term: 0x420fa40>,
        <Term: 0x4257bd0>,
        <Term: 0x4257cf0>,
        <Term: 0x4257d90>,
        <Term: 0x4257e30>
    ),
        (
        <Term: 0x4257e50>,
        <Term: 0x4257f90>,
        <Term: 0x4257fb0>,
        <Term: 0x42580e0>,
        <Term: 0x4258170>,
        <Term: 0x4258210>,
        <Term: 0x4258230>,
        <Term: 0x4258360>,
        <Term: 0x4258400>,
        <Term: 0x42584a0>,
        <Term: 0x4258540>,
        <Term: 0x42585e0>,
        <Term: 0x4258670>,
        <Term: 0x4258710>
    ),

А вот мой код для поисковой части моей таблицы:

- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section 
{
    // Normal table
    if (aTableView == self.tableView) return [[self.sectionArray objectAtIndex:section] count];

    // Search table
    //NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@", self.searchBar.text];
    //self.filteredArray = [self.crayonColors filteredArrayUsingPredicate:predicate];
 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@", self.searchBar.text];
    self.filteredArray = [[self.sectionArray objectAtIndex:section] filteredArrayUsingPredicate:predicate];


    return self.filteredArray.count;
}

Я получаю ошибку, что не могу выделить достаточно места, что означает, что я, должно быть, делаю что-то не так, я просто не могу понять, что.

Закомментированная часть поисковой части в вышеприведенном методе работает, но crayonColors - это просто NSMutableDictionary из NSStrings и не имеет массивов, вложенных в него.

Заранее спасибо!

1 Ответ

11 голосов
/ 31 декабря 2010

Насколько я знаю, вы не можете сделать это с помощью одного предиката.Однако вы можете сделать это с помощью оператора ключевого пути и предиката в двух отдельных вызовах.

Итак, у вас есть массив массивов терминов.Вы хотите один массив терминов, где его имя содержит «A» (например).Вот что вы делаете:

NSArray * allTerms = ...; //your array of arrays of terms
NSArray * collapsedTerms = [allTerms valueForKeyPath:@"@unionOfArrays.self"];

NSPredicate * filter = [NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@", @"A"];
NSArray * filteredTerms = [collapsedTerms filteredArrayUsingPredicate:filter];

Волшебство здесь - бит valueForKeyPath:.Оператор @unionOfArrays принимает массив массивов объектов и возвращает массив объектов.Вот что он делает: NSArray собирается разбить траекторию на ., давая ей @unionOfArrays и self.Он собирается повторить и вызвать valueForKeyPath: сам по себе, используя второй бит (self), и вернет массив массивов.Затем он собирается объединить все эти массивы в один массив, игнорируя дубликаты.(Если вы хотите удалить дубликаты, используйте @distinctUnionOfArrays вместо этого)

После того, как у нас будет этот массив объектов, мы можем затем отфильтровать его, как правило, используя простой предикат name CONTAINS 'blah'.Я подумал, что смогу заставить это работать, используя SUBQUERY, но это странный зверь, и для меня ничего не было сразу очевидно.используя расширения коллекции KickingBear ( доступно здесь ), но я бы настоятельно рекомендовал не использовать подобные хаки в производственных условиях.:)

...