iOS CoreData NSPredicate 一次查询多个属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10611362/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS CoreData NSPredicate to query multiple properties at once
提问by OscarTheGrouch
I am trying to use a UISearchBar
to query multiple properties of a NSManagedObject
I have a NSManagedObject
called Person
, every person has a name
and socialSecurity
property. Right now my code can perform a search (fetch) for one of those properties or the other, but not both at the same time.
我正在尝试使用 aUISearchBar
来查询NSManagedObject
我有一个NSManagedObject
被调用的多个属性Person
,每个人都有一个name
和socialSecurity
属性。现在,我的代码可以对这些属性之一执行搜索(获取),但不能同时对这两个属性执行搜索(获取)。
- (void) performFetch
{
[NSFetchedResultsController deleteCacheWithName:@"Master"];
// Init a fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"MainObject" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Apply an ascending sort for the color items
//NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Term" ascending:YES selector:nil];
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"fullName" ascending:YES selector:@selector(caseInsensitiveCompare:)];
NSArray *descriptors = [NSArray arrayWithObject:sortDescriptor];
[fetchRequest setSortDescriptors:descriptors];
// Recover query
NSString *query = self.searchDisplayController.searchBar.text;
//if (query && query.length) fetchRequest.predicate = [NSPredicate predicateWithFormat:@"Term contains[cd] %@", query];
if(searchValue==1)
{
if (query && query.length) fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@", query];
}
else {
if (query && query.length) fetchRequest.predicate = [NSPredicate predicateWithFormat:@"socialSecurity contains[cd] %@", query];
}
// Init the fetched results controller
NSError *error;
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"pLLetter" cacheName:nil];
self.fetchedResultsController.delegate = self;
if (![[self fetchedResultsController] performFetch:&error]) NSLog(@"Error: %@", [error localizedDescription]);
[self.tableView reloadData];
}
I don't know how to put both properties into this statement...
我不知道如何将这两个属性放入此语句中...
if (query && query.length) fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@", query];
Any help or ideas would be greatly appreciated.
任何帮助或想法将不胜感激。
回答by Matthias Bauch
You could use a NSCompoundPredicate
.
你可以使用一个NSCompoundPredicate
.
Like this:
像这样:
NSPredicate *predicateName = [NSPredicate predicateWithFormat:@"name contains[cd] %@", query];
NSPredicate *predicateSSID = [NSPredicate predicateWithFormat:@"socialSecurity contains[cd] %@", query];
NSArray *subPredicates = [NSArray arrayWithObjects:predicateName, predicateSSID, nil];
NSPredicate *orPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
request.predicate = orPredicate;
there is a NSCompoundPredicate
for AND
too: andPredicateWithSubpredicates:
有一NSCompoundPredicate
对AND
过:andPredicateWithSubpredicates:
回答by CaptainRedmuff
You can append multiple search terms in an NSPredicate
using the usual boolean operands such as AND/OR.
您可以NSPredicate
使用通常的布尔操作数(例如 AND/OR)在 an 中附加多个搜索词。
Something like this should do the trick.
像这样的事情应该可以解决问题。
[NSPredicate predicateWithFormat:@"name contains[cd] %@ OR ssid contains[cd] %@", query, query];
Hope that helps :)
希望有帮助:)
回答by Onur Var
Addition to @Matthias's answer, you can also use NSCompoundPredicate for your AND operations like this.
除了@Matthias 的回答之外,您还可以将 NSCompoundPredicate 用于这样的 AND 操作。
Obj-C - AND
Obj-C - 与
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate1, predicate2]];
Swift - AND
斯威夫特 - 和
let predicate1:NSPredicate = NSPredicate(format: "X == 1")
let predicate2:NSPredicate = NSPredicate(format: "Y == 2")
let predicate:NSPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate1,predicate2] )
Swift 3 - AND
斯威夫特 3 - 和
let predicate1 = NSPredicate(format: "X == 1")
let predicate2 = NSPredicate(format: "Y == 2")
let predicateCompound = NSCompoundPredicate(type: .and, subpredicates: [predicate1,predicate2])
回答by Vincent
Complete solution for Swift2
Swift2 的完整解决方案
let request = NSFetchRequest(entityName: "Location")
let subPredicate1 = NSPredicate(format: "(name = %@)", searchString)
let subPredicate2 = NSPredicate(format: "(street = %@)", searchString)
let subPredicate3 = NSPredicate(format: "(city = %@)", searchString)
request.predicate = NSCompoundPredicate(type: .OrPredicateType, subpredicates: [subPredicate1, subPredicate2, subPredicate3])
回答by MFarmer
To avoid the warning Incompatible pointer types initializing 'NSCompoundPredicate *_strong' with an expression of type 'NSPredicate *', replace the following:
为避免使用类型为 'NSPredicate *' 的表达式初始化 'NSCompoundPredicate *_strong'的警告不兼容的指针类型,请替换以下内容:
NSCompoundPredicate * predicate = [NSCompoundPredicate orPredicateWithSubPredicates:subPredicates];
with this:
有了这个:
NSPredicate * predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
Source: NSCompoundPredicate
回答by Bean
Fraser Hess over at CISMGF.com has a great search example. You can read the post at http://www.cimgf.com/2008/11/25/adding-itunes-style-search-to-your-core-data-application/
在 CISMGF.com 上的 Fraser Hess 有一个很好的搜索示例。您可以在http://www.cimgf.com/2008/11/25/adding-itunes-style-search-to-your-core-data-application/阅读帖子
My code based off the post is:
我基于帖子的代码是:
NSArray *searchTerms = [searchText componentsSeparatedByString:@" "];
if ([searchTerms count] == 1) { // Search in name and description
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(name contains[cd] %@) OR (desc contains[cd] %@)", searchText, searchText];
[self.searchFetchedResultsController.fetchRequest setPredicate:predicate];
} else { // Search in name and description for multiple words
NSMutableArray *subPredicates = [[NSMutableArray alloc] init];
for (NSString *term in searchTerms) {
NSPredicate *pred = [NSPredicate predicateWithFormat:@"(name contains[cd] %@) OR (desc contains[cd] %@)", term, term];
[subPredicates addObject:pred];
}
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];
[self.searchFetchedResultsController.fetchRequest setPredicate:predicate];
}
回答by tiritea
This is may be useful if you want to search multiple properties for anything that matches (eg UISearchControllerDelegate):
如果您想搜索多个属性以查找匹配的任何内容(例如 UISearchControllerDelegate),这可能很有用:
NSString *searchFor = @"foo";
NSArray *fields = @[@"Surname", @"FirstName", @"AKA", @"Nickname"]; // OR'd dictionary fields to search
NSMutableArray *predicates = NSMutableArray.new;
for (NSString *field in fields) {
[predicates addObject:[NSPredicate predicateWithFormat:@"(%K BEGINSWITH[cd] %@)", field, searchFor]];
}
NSPredicate *search = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
You could then use this, for example, to filter an array of dictionaries:
例如,您可以使用它来过滤字典数组:
NSArray *results = [bigArray filteredArrayUsingPredicate:search];
(the BEGINSWITH[cd] is no magic, just means it'll match beginnings of strings and case-insensitive. Change as needed for your match criteria.)
( BEGINSWITH[cd] 不是魔术,只是意味着它将匹配字符串的开头并且不区分大小写。根据您的匹配条件进行更改。)
回答by Dhavaprathap
For Swift:
对于斯威夫特:
var predicate = NSCompoundPredicate(
type: .AndPredicateType,
subpredicates: [predicate1, predicate2]
)