выборка объектов из основных данных, не входящих в набор - PullRequest
24 голосов
/ 31 мая 2011

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

Например, предположим, что у нас есть данные ядрасущность с именем User, которая имеет несколько атрибутов, таких как userName, familyName, GivenName и active.Учитывая массив строк, представляющих набор имен пользователей, мы можем легко выбрать всех пользователей, соответствующих этому списку имен пользователей:

NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"User"
                                          inManagedObjectContext:moc];
[request setEntity:entity];

NSArray *userNames = [NSArray arrayWithObjects:@"user1", @"user2", @"user3", nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"userName IN %@", userNames];
[request setPredicate:predicate];
NSArray *users = [moc executeFetchRequest:request error:nil];

Однако я хочу получить дополнение этого набора, т.е. я хочувсе пользователи в основных данных, которые не имеют имен пользователей, указанных в массиве userNames.У кого-нибудь есть идеи как подойти к этому вопросу?Я думал, что было бы достаточно просто добавить "NOT" в предикат (i.e., "userName NOT IN %@"), но XCode выдает исключение, говорящее о том, что формат предиката не может быть проанализирован.Я также безуспешно пытался использовать построитель предикатов, доступный для запросов на выборку.Документация также не была особенно полезной.Предложения?Комментарии?Спасибо за вашу помощь:)

Ответы [ 3 ]

58 голосов
/ 31 мая 2011

Чтобы найти объекты, которых нет в вашем массиве, все, что вам нужно сделать, это примерно так:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (userName IN %@)", userNames];

Это должно вернуть запрос всех объектов без указанных вами.

1 голос
/ 28 сентября 2012

Я не силен в базовых данных / target-c, но предикат должен быть похож на следующее утверждение:

[predicateFormat appendFormat:@"not (some_field_name in {'A','B','B','C'})"];

Пример:

NSMutableString * mutableStr = [[NSMutableString alloc] init];

//prepare filter statement
for (SomeEntity * e in self.someArray) {
    [mutableStr appendFormat:@"'%@',", e.key];
}

//excluded objects exist
if (![mutableStr isEqual:@""])
{
    //remove last comma from mutable string
    mutableStr = [[mutableStr substringToIndex:mutableStr.length-1] copy];

    [predicateFormat appendFormat:@"not (key in {%@})", mutableStr];
}

//...
//use this predicate in NSFetchRequest
//fetchRequest.predicate = [NSPredicate predicateWithFormat:predicateFormat];
//...   
0 голосов
/ 09 марта 2015

Вот еще один полезный пример, показывающий, как взять список строк и отфильтровать все, которые НЕ начинаются с букв A-Z:

NSArray* listOfCompanies = [NSArray arrayWithObjects:@"123 Hello", @"-30'c in Norway", @"ABC Ltd", @"British Rail", @"Daily Mail" @"Zylophones Inc.", nil];

NSPredicate *bPredicate = [NSPredicate predicateWithFormat:@"NOT (SELF MATCHES[c] '^[A-Za-z].*')"];

NSArray *filteredList = [listOfCompanies filteredArrayUsingPredicate:bPredicate];

for (NSString* oneCompany in filteredList)
    NSLog(@"%@", oneCompany);

Я использую этот тип NSPredicate, когда я заполняю UITableView индексом A-Z и хочу раздел «все остальное» для элементов, которые не начинаются с буквы.

...