2012-05-16 5 views
18

Ich versuche, eine UISearchBar zu verwenden, um mehrere Eigenschaften eines NSManagedObject abzufragen Ich habe ein NSManagedObject genannt Person, jede Person, die ein name und socialSecurity Eigenschaft hat. Im Moment kann mein Code eine Suche (Fetch) für eine dieser Eigenschaften oder die andere durchführen, aber nicht beide gleichzeitig.iOS Coredata NSPredicate an mehreren Eigenschaften abfragen einmal

- (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]; 
} 

Ich weiß nicht, wie beide Eigenschaften in dieser Aussage setzen ...

if (query && query.length) fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@", query]; 

Jede Hilfe oder Anregungen wäre sehr dankbar.

Antwort

26

Sie können mehrere Suchbegriffe in einem NSPredicate mit den üblichen booleschen Operanden wie AND/OR anhängen.

So etwas sollte den Trick machen.

[NSPredicate predicateWithFormat:@"name contains[cd] %@ OR ssid contains[cd] %@", query, query]; 

Hoffnung, das hilft :)

+1

if (query && query.length) fetchRequest.predicate = [NSPredikat-PrädikatWithFormat: @ "(fullName enthält [cd]% @) || (socialSecurity enthält [cd]% @) ", Abfrage, Abfrage]; – OscarTheGrouch

31

Sie einen NSCompoundPredicate nutzen könnten.

So:

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; 

gibt es eine NSCompoundPredicate für AND zu: andPredicateWithSubpredicates:

+2

+1 für die Verwendung von NSCompoundPredicate. – CaptainRedmuff

+0

NSArray * subPredicates = @ [PrädikatName, PrädikatSSID]; Ich mag die Objective C 2.0 NSArray Syntax, Just Saying –

4

Um die Warnung Inkompatible Zeigertypen zu vermeiden Initialisierung 'NSCompoundPredicate * _strong' mit einem Ausdruck des Typs 'NSPredicate *', ersetzen Sie die folgenden:

NSCompoundPredicate * predicate = [NSCompoundPredicate orPredicateWithSubPredicates:subPredicates]; 

mit diesem:

NSPredicate * predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates]; 

Quelle: NSCompoundPredicate

1

Fraser Hess über bei CISMGF.com hat eine große Such Beispiel. Sie können die Post bei http://www.cimgf.com/2008/11/25/adding-itunes-style-search-to-your-core-data-application/

Mein Code lesen basiert off der Post ist:

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]; 
} 
0

Für Swift:

var predicate = NSCompoundPredicate(
     type: .AndPredicateType, 
     subpredicates: [predicate1, predicate2] 
    ) 
4

Komplettlösung für 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]) 
8

Zusatz @ Matthias's Antwort, Sie können NSCompoundPredicate auch für Ihre UND-Operationen verwenden.

Obj-C - UND

NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"]; 
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"]; 
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate1, predicate2]]; 

Swift - UND

let predicate1:NSPredicate = NSPredicate(format: "X == 1") 
let predicate2:NSPredicate = NSPredicate(format: "Y == 2") 
let predicate:NSPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate1,predicate2]) 

Swift 3 - UND

let predicate1 = NSPredicate(format: "X == 1") 
    let predicate2 = NSPredicate(format: "Y == 2") 
    let predicateCompound = NSCompoundPredicate(type: .and, subpredicates: [predicate1,predicate2]) 
1

Dies wird nützlich sein können ful, wenn Sie mehrere Objekte für etwas suchen möchten, die (zB UISearchControllerDelegate) entspricht:

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]; 

Sie dann diese zum Beispiel verwenden könnte, eine Reihe von Wörterbüchern zu filtern:

NSArray *results = [bigArray filteredArrayUsingPredicate:search]; 

(die BEGINSWITH [cd] ist keine Zauberei, es bedeutet nur, dass die Strings anfängt und die Groß-/Kleinschreibung nicht beachtet wird. Ändern Sie nach Bedarf für Ihre Abgleichskriterien.)