【问题标题】:iOS CoreData NSPredicate to query multiple properties at onceiOS CoreData NSPredicate 一次查询多个属性
【发布时间】:2012-05-23 14:12:34
【问题描述】:

我正在尝试使用UISearchBar 来查询NSManagedObject 的多个属性 我有一个名为PersonNSManagedObject,每个人都有一个namesocialSecurity 属性。现在我的代码可以搜索(获取)其中一个属性或另一个,但不能同时搜索。

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

我不知道如何将这两个属性都放入这个语句中......

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

任何帮助或想法将不胜感激。

【问题讨论】:

    标签: ios core-data nspredicate nsfetchrequest


    【解决方案1】:

    除了@Matthias 的回答,您还可以像这样使用 NSCompoundPredicate 进行 AND 操作。

    Obj-C - 与

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

    斯威夫特 - 与

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

    Swift 3 - 与

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

    【讨论】:

      【解决方案2】:

      如果您想在多个属性中搜索任何匹配的内容(例如 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];
      

      然后,您可以使用它来过滤字典数组:

      NSArray *results = [bigArray filteredArrayUsingPredicate:search];
      

      (BEGINSWITH[cd] 并不神奇,只是意味着它将匹配字符串的开头并且不区分大小写。根据您的匹配条件进行更改。)

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

          对于斯威夫特:

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

          【讨论】:

            【解决方案5】:

            CISMGF.com 上的 Fraser Hess 有一个很好的搜索示例。您可以在http://www.cimgf.com/2008/11/25/adding-itunes-style-search-to-your-core-data-application/阅读帖子

            我基于帖子的代码是:

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

            【讨论】:

              【解决方案6】:

              您可以使用NSCompoundPredicate

              像这样:

              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;
              

              AND 也有一个NSCompoundPredicateandPredicateWithSubpredicates:

              【讨论】:

              • NSArray *subPredicates = @[predicateName, predicateSSID];我喜欢 Objective C 2.0 NSArray 语法,只是说
              【解决方案7】:

              为避免警告Incompatible pointer types initializing 'NSCompoundPredicate *_strong' with an expression of type 'NSPredicate *',请替换以下内容:

              NSCompoundPredicate * predicate = [NSCompoundPredicate orPredicateWithSubPredicates:subPredicates];
              

              用这个:

              NSPredicate * predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
              

              来源:NSCompoundPredicate

              【讨论】:

                【解决方案8】:

                您可以使用常见的布尔操作数(例如 AND/OR)在 NSPredicate 中附加多个搜索词。

                这样的事情应该可以解决问题。

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

                希望有帮助:)

                【讨论】:

                • if (query && query.length) fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(fullName contains[cd] %@) || (socialSecurity contains[cd] %@)",query,查询];
                猜你喜欢
                • 1970-01-01
                • 2012-03-28
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-01-20
                • 1970-01-01
                相关资源
                最近更新 更多