Подтвердить что ты не робот

Как присоединиться к двум строкам для NSPredicate, то есть firstname и lastname

У меня есть объект Person, который имеет два свойства NSString; firstName and lastName. В настоящее время я использую NSPredicate так:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(firstName contains[cd] %@) OR (lastName contains[cd] %@)", searchText, searchText];

Итак, например, скажем, я ищу имя "John Smith". В моей строке поиска, если я набираю "Joh", тогда John Smith появится как опция. Это хорошо и хорошо, но если я наберу "John Sm", он будет пустым.

Как я могу присоединиться к firstName и lastName в predicate, поэтому, если бы я искал "John Sm", тогда John Smith все равно будет отображаться как опция.

Надеюсь, это имеет смысл. Спасибо.

EDIT: Чтобы добавить немного больше пояснений, я использую метод делегата SearchDisplayController:

-(void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope;

и я использую predicate следующим образом:

newArray = [personObjectArray filteredArrayUsingPredicate:predicate];
4b9b3361

Ответ 1

Попробуйте это,

NSString *text = @"John Smi";
NSString *searchText = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

NSArray *array = [searchText componentsSeparatedByString:@" "];
NSString *firstName = searchText;
NSString *lastName = searchText;
NSPredicate *predicate = nil;

if ([array count] > 1) {
    firstName = array[0];
    lastName = array[1];
    predicate = [NSPredicate predicateWithFormat:@"(firstName CONTAINS[cd] %@ AND lastName CONTAINS[cd] %@) OR (firstName CONTAINS[cd] %@ AND lastName CONTAINS[cd] %@)", firstName, lastName, lastName, firstName];
} else {
    predicate = [NSPredicate predicateWithFormat:@"firstName CONTAINS[cd] %@ OR lastName CONTAINS[cd] %@", firstName, lastName];
}

NSArray *filteredArray = [people filteredArrayUsingPredicate:predicate];
NSLog(@"%@", filteredArray);

Вывод:

(
        {
        firstName = John;
        lastName = Smith;
    }
)

Здесь текст представляет искомый текст. Преимущество вышеизложенного состоит в том, что даже если вы пройдете text = @"Smi Joh"; или text = @"John "; или text = @" smi"; или text = @"joh smi ";, он все равно покажет вышеприведенный вывод.

Ответ 2

вы можете объединить поля в два общих поля (firstLastName и lastFirstName)

- (NSString *)firstLastName {
      return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}

- (NSString *)lastFirstName {
      return [NSString stringWithFormat:@"%@ %@", self.lastName, self.firstName];
}

а затем отфильтруйте по этим полям, используя 'contains [cd]'

[NSPredicate predicateWithFormat:@"(firstLastName contains[cd] %@) OR (lastFirstName contains[cd] %@)" , self.searchBar.text, self.searchBar.text];

Ответ 3

Решение, предложенное выше, не будет работать со строками поиска, содержащими более двух слов. Вот более тщательная реализация в быстром. Это решение также позволяет добавлять дополнительные поля в запись, если ваша цель - реализовать полнотекстовый поиск по имени, электронной почте, номеру телефона и т.д. В этом случае просто обновите NSPredicate до OR newField CONTAINS[cd] %@ и обязательно добавьте дополнительные $0 в списке замены строк.

let searchText = search.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
let words = searchText.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
let predicates = words.map { NSPredicate(format: "firstName CONTAINS[cd] %@ OR lastName CONTAINS[cd] %@", $0,$0) }

let request = NSFetchRequest()
request.predicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates)