嵌套对象 IOS 的 NSPredicate 问题

Posted

技术标签:

【中文标题】嵌套对象 IOS 的 NSPredicate 问题【英文标题】:NSPredicate issue for Nested objects IOS 【发布时间】:2014-12-05 06:47:19 【问题描述】:

我如何在“self.tableInfo”(NSMutableArray) 上使用NSPredicate 使用具有以下结构的谓词键“name”来获取CheckIn 的对象。因为 self.tableInfo 有一个 SectionInfo 数组,每个 SectionInfo 里面都有它的单元格(CellInfo),每个单元格都有签入对象。

- (void)configureView   
    self.tableInfo = [NSMutableArray alloc]init];
    self.filteredTableInfo = [NSMutableArray alloc]init];
    NSArray *checkIns =  [CheckIn MR_findAll];
    SectionInfo*checkInSection = [SectionInfo section];
    for (CheckIn *checkIn in checkIns) 
        CellInfo *listCell = (CellInfo *)[CellInfo cell];
        listCell.className = NSStringFromClass([FeedListCell class]);
        listCell.height = 260;
        listCell.object = checkIn;
        [checkInSection.cells addObject:listCell];
    
    if ([checkIns count] > 0) 
        self.tableInfo = [NSMutableArray arrayWithArray:@[checkInSection]];
        self.filteredTableInfo = self.tableInfo;
        [self.tableView setHidden:NO];
        [self.tableView reloadData];
    


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
    if (self.tableInfo) 
        return self.tableInfo.count;
    
    return 0;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    if (self.tableInfo && (section < self.tableInfo.count) ) 
        SectionInfo *sectionInfo = [self.tableInfo objectAtIndex:section];
        return sectionInfo.numberOfCells;
    
    return 1;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    SectionInfo *sectionInfo = self.tableInfo[indexPath.section];
    CellInfo *formInfoCell = sectionInfo.cells[indexPath.row];
    CheckIn *checkin = formInfoCell.object;
    NSLog(@"%@", checkIn.name);

我使用的方式是这样的:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText 
    if([searchText length] != 0) 
        [self filterContentForSearchText:searchText];
    

- (void)filterContentForSearchText:(NSString *)searchText   
    NSPredicate *namePredicate = [NSPredicate predicateWithFormat:@"ANY cells.object.name contains[c] %@", searchText];
    NSArray * filteredArray = [self.filteredTableInfo filteredArrayUsingPredicate:namePredicate];
    self.tableInfo = [NSMutableArray arrayWithArray:@[filteredArray]];
    [self.tableView reloadData];

这总是返回零计数。有更好的办法来处理这件事吗?

【问题讨论】:

【参考方案1】:

看起来您在使用此谓词时遇到了一些问题。首先,在您的谓词中,您正在搜索基于“CellInfo.object”SELF.cells.object contains[c] %@ 而不是“CellInfo.object.name”,就像您想要做的那样。

其次,在数组中搜索数组时(在您的情况下是 tableInfo 数组中的 SectionInfo.cells ),您不能简单地使用点符号来搜索内部数组。您必须在数组中指定与您的查询匹配的项目。您可以使用关键字ANYALLNONE 之一来执行此操作。

例如,要获取具有 CellInfo 且 CheckIn.name 包含您想要执行的搜索文本的任何 SectionInfo:

NSPredicate *namePredicate = [NSPredicate predicateWithFormat:@"ALL cells.object.name contains[c] %@", searchText"];
NSArray *filteredSections = [self.tableInfo filteredArrayUsingPredicate:namePredicate]

但是,这会返回一个 SectionInfo 数组,而不是您想要的 CheckIn 对象。为了获得 CheckIn 对象,您必须首先创建一个包含所有 CheckIn 对象的数组。您可以通过在 NSArray 上使用 valueForKeyPath 方法来做到这一点。然后,您可以使用更简单的谓词搜索该数组。

NSArray *allCheckInObjects = [self.tableInfo valueForKeyPath:@"@distinctUnionOfArrays.cells.object"];
NSPredicate *namePredicate = [NSPredicate predicateWithFormat:@"name contains[c] %@", searchText];
NSArray *filteredCheckInObjects = [allCheckInObjects filteredArrayUsingPredicate:namePredicate];

希望这会有所帮助!

【讨论】:

谢谢。我尝试使用您的方法,例如: NSPredicate *namePredicate = [NSPredicate predicateWithFormat:@"ALL cells.object.name contains[c] %@", searchText]; NSArray *filteredSections = [self.tableInfo filteredArrayUsingPredicate:namePredicate];但结果始终是一个空数组。我需要 sectionInfo 对象。 您确定 self.tableInfo 在搜索之前已初始化并填充吗?我会 NSLog() 数组并确保您可以使用谓词找到要搜索的对象,以确保它确实是失败的谓词。 是的,我再次检查过。这是我在控制台中使用“Po self.tableInfo”以及使用 NSLog() 时的日志。 NSLog(@"self.tableInfo before predicate :%@", self.tableInfo);谓词前的 self.tableInfo :( "" ) NSLog(@"filteredSections :%@", filteredSections); filtersedSections :( ) NSLog(@"filteredSections 数组计数 :%lu", (unsigned long)[filteredSections count]); filterSections 数组计数:0 我确定搜索键“a”在我的 Checkin 对象中。 啊,我明白了问题所在。我错误地指定了ALL 而不是ANYALL 要求该部分中的每个单元格都必须与谓词匹配。 ANY 指定任何匹配谓词的单元格就足够了。使用ANY 我使用了“ANY”而不是“ALL”。现在它向我显示了一个 sectionInfo 对象,并且 sectionInfo 内部的单元格计数为零。我可以做子查询吗?像这样的东西:***.com/questions/13242383/…【参考方案2】:

我通过以下代码解决。我在单个数组中有“最近”和“其他”数组我在每个数组中应用谓词。并且搜索条件是“from_user”NSDictionary 中的“名称”。

-(void)filterContentForSearchText:(NSString *)searchText

    [self.filterResultArray removeAllObjects];
    NSPredicate *namePredicate = [NSPredicate predicateWithFormat:@"(from_user.name contains[cd] %@)", searchText];

    NSMutableArray *recentSearch=[[NSMutableArray alloc] init];
    //Recent
    if ([[[self connectioUserArray] objectAtIndex:1] count]==0) 
        //Recent is blank
    
    else
        //else
        recentSearch=[[[[self connectioUserArray] objectAtIndex:0] filteredArrayUsingPredicate:namePredicate] mutableCopy];
    

    //other
    self.filterResultArray = [[[[self connectioUserArray] objectAtIndex:1] filteredArrayUsingPredicate:namePredicate] mutableCopy];

    if ([recentSearch count]==0) 
        //no records
    
    else
        //if recent records
        for (NSMutableDictionary *recentConnectoin in recentSearch) 
            [self.filterResultArray addObject:recentConnectoin];
        
    

    //Reload table view
    [self.tableView reloadData];


【讨论】:

以上是关于嵌套对象 IOS 的 NSPredicate 问题的主要内容,如果未能解决你的问题,请参考以下文章

以 NSDictionary 作为对象的嵌套数组上的 NSPredicate

NSPredicate 嵌套字典动态键

带有嵌套数组的 NSPredicate

NSPredicate 针对 NSArray 中的嵌套值

使用嵌套的 NSPredicate SUBQUERY

iOS核心数据如何使用NSPredicate根据一对多的子属性查找父对象?