Ios Objective-C-NSPredicate-筛选器NSArray,其中包含包含自定义对象NSArray的字典

Ios Objective-C-NSPredicate-筛选器NSArray,其中包含包含自定义对象NSArray的字典,ios,objective-c,uitableview,uisearchbar,nspredicate,Ios,Objective C,Uitableview,Uisearchbar,Nspredicate,在我的应用程序中,我在带有分区的UItableView中显示联系人列表。我的数据源是一个NSMutableArray保存NSDictionaries,它保存两种自定义对象类型的数组(请参见下文debugDescription) 第一部分显示联系人组名称(SNPgroupData.groupName),其余部分显示按其SNPcontactData.contactName属性的第一个字母排序的联系人。 这一切都很好,当我想在tableView中搜索特定项时,问题就来了 是否可以使用NSpredica

在我的应用程序中,我在带有分区的
UItableView
中显示联系人列表。我的数据源是一个
NSMutableArray
保存
NSDictionaries
,它保存两种自定义对象类型的数组(请参见下文
debugDescription

第一部分显示联系人组名称(
SNPgroupData.groupName
),其余部分显示按其
SNPcontactData.contactName
属性的第一个字母排序的联系人。 这一切都很好,当我想在tableView中搜索特定项时,问题就来了

是否可以使用
NSpredicate
(或其他方法)筛选任何属性包含(
包含[c]@”、searchText?
)搜索字符串的项目(组和联系人)

以下
NSArray
是my
UItableView
的数据源:

  {
        Groups =     (
            "<SNPgroupData: 0x16e5ae80>",
            "<SNPgroupData: 0x16d9ff80>"
        );
    },
    {
        A =     (
            "<SNPContactData: 0x16dd5fd0>",
            "<SNPContactData: 0x16d8a840>",
            "<SNPContactData: 0x16dd68b0>",
            "<SNPContactData: 0x16dd7a10>",
            "<SNPContactData: 0x16dcef60>",
            "<SNPContactData: 0x16d9dc90>",
            "<SNPContactData: 0x16dd6950>",
            "<SNPContactData: 0x16db5070>",
            "<SNPContactData: 0x16d98820>",
            "<SNPContactData: 0x16dac810>",
            "<SNPContactData: 0x16d8e510>",
            "<SNPContactData: 0x16dbf5d0>",
            "<SNPContactData: 0x16dcfbd0>"
        );
    },
    {
        B =     (
            "<SNPContactData: 0x16dae7b0>",
            "<SNPContactData: 0x16dd6ef0>",
            "<SNPContactData: 0x16dd9f90>",
            "<SNPContactData: 0x16d8e480>",
            "<SNPContactData: 0x16d9c750>",
            "<SNPContactData: 0x16d9ba20>",
            "<SNPContactData: 0x16d9ba40>",
            "<SNPContactData: 0x16dd6e20>"
        );
    },
    {
        C =     (
            "<SNPContactData: 0x16dcf790>"
        );
    },
我能够从数组中过滤出组对象,但我得到了所有对象,而不仅仅是以我的searchText字符开头的对象。 试图让contact谓词以不同的方式工作,但由于每个谓词的数组名称都不同,因此谓词要么不做任何事情,要么使应用程序崩溃(无法解析)

据我所知,没有直接的方法将筛选器应用于应用程序的“内部数组” 并返回相同结构的新数据源数组

您必须使用如下谓词分别筛选每个自定义对象数组

[NSPredicate predicateWithFormat:@"groupName CONTAINS[c] %@", searchText] // for groups
[NSPredicate predicateWithFormat:@"contactName CONTAINS[c] %@", searchText] // for contacts

然后构建一个新的数据源阵列。

通过以稍微不同的方式处理问题,您可以让事情变得更加简单:

  • 使用而不是手动分割联系人信息
  • 将组名与联系人存储在单独的数组属性中。您可以在“表视图数据源”部分进行切换以提取正确的数据
  • 如果您确实需要使用谓词来过滤数据,并且不知道如何使用谓词语法,请使用

已经有一段时间了,但无论如何,我最终还是采用了以下方法: -两个独立的过滤过程 -组筛选相当简单,因为我有一个字典,其中包含通过计算groupName属性筛选的组对象 -对于联系人,我有多个字典(表示姓名以特定字母开头的联系人)我决定检查用户输入的第一个字母,提取相关字典,然后计算联系人姓名。是的,这种方法只适用于以特定搜索查询开始的联系人姓名,但它符合我的需要

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

if ([searchText isEqualToString:@""]) {
    self.showFiltered=NO;
    [self.contactsTable reloadData];

}else{
    NSLog(@"%@",[self.contactGroups debugDescription]);

    NSPredicate *groupNamePredicate = [NSPredicate predicateWithBlock:
                                       ^BOOL(id evaluatedObject, NSDictionary *bindings)
                                       {
                                           return [[[evaluatedObject groupName] substringToIndex:searchText.length] isEqualToString:searchText];;
                                       }];

    self.filteredContactGroups = [[NSArray alloc]initWithArray:[self.contactGroups filteredArrayUsingPredicate:groupNamePredicate]];


    NSLog(@"filtered Names: %@", self.filteredAppContacts);

    NSString *firstLetter = [searchText substringToIndex:1];

    NSMutableArray *filteredContacts = [[NSMutableArray alloc]init];

    for (NSDictionary *letterDictionary in self.groupedAppContacts) {
        if ([letterDictionary objectForKey:[firstLetter uppercaseString]]) {
            filteredContacts = [letterDictionary objectForKey:[firstLetter uppercaseString]];
        }
    }
    if (filteredContacts.count>1) {
        NSPredicate *contactNamePredicate = [NSPredicate predicateWithBlock:
                                             ^BOOL(id evaluatedObject, NSDictionary *bindings)
                                             {
                                                 return [[[evaluatedObject contactName] substringToIndex:searchText.length+1] caseInsensitiveCompare:searchText];
                                             }];


        self.filteredAppContacts = [[NSArray alloc]initWithArray:[filteredContacts filteredArrayUsingPredicate:contactNamePredicate]];


        NSLog(@"filtered Names: %@", filteredContacts);
    }else{
        self.filteredAppContacts = [[NSArray alloc]initWithArray:filteredContacts];
    }

    self.showFiltered=YES;
    [self.contactsTable reloadData];

}

}

难道不能运行两个子谓词,然后在主谓词中要求两个子谓词返回的对象都大于零吗?我有点晕眩,因为感冒了,所以我可能错了。@LeoNatan:
FilteredarrayingPredicate
返回一个“子数组”“原始数组的,但这里我们需要具有修改元素的数组。-我能想到的唯一替代方法是,如果内部数组是可变的,则将
FilterSingPredicate
应用于它们。但这将修改原始数据源。-早日康复!谢谢各位。我在你的评论后发布了一篇编辑文章。仍然无法单独筛选出对象。任何帮助都将不胜感激!在我的下一个版本中,我想实现您的方法,它是否适用于以多种语言存储联系人姓名的用户?
-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {

if ([searchText isEqualToString:@""]) {
    self.showFiltered=NO;
    [self.contactsTable reloadData];

}else{
    NSLog(@"%@",[self.contactGroups debugDescription]);

    NSPredicate *groupNamePredicate = [NSPredicate predicateWithBlock:
                                       ^BOOL(id evaluatedObject, NSDictionary *bindings)
                                       {
                                           return [[[evaluatedObject groupName] substringToIndex:searchText.length] isEqualToString:searchText];;
                                       }];

    self.filteredContactGroups = [[NSArray alloc]initWithArray:[self.contactGroups filteredArrayUsingPredicate:groupNamePredicate]];


    NSLog(@"filtered Names: %@", self.filteredAppContacts);

    NSString *firstLetter = [searchText substringToIndex:1];

    NSMutableArray *filteredContacts = [[NSMutableArray alloc]init];

    for (NSDictionary *letterDictionary in self.groupedAppContacts) {
        if ([letterDictionary objectForKey:[firstLetter uppercaseString]]) {
            filteredContacts = [letterDictionary objectForKey:[firstLetter uppercaseString]];
        }
    }
    if (filteredContacts.count>1) {
        NSPredicate *contactNamePredicate = [NSPredicate predicateWithBlock:
                                             ^BOOL(id evaluatedObject, NSDictionary *bindings)
                                             {
                                                 return [[[evaluatedObject contactName] substringToIndex:searchText.length+1] caseInsensitiveCompare:searchText];
                                             }];


        self.filteredAppContacts = [[NSArray alloc]initWithArray:[filteredContacts filteredArrayUsingPredicate:contactNamePredicate]];


        NSLog(@"filtered Names: %@", filteredContacts);
    }else{
        self.filteredAppContacts = [[NSArray alloc]initWithArray:filteredContacts];
    }

    self.showFiltered=YES;
    [self.contactsTable reloadData];

}