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
是myUItableView
的数据源:
{
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
然后构建一个新的数据源阵列。通过以稍微不同的方式处理问题,您可以让事情变得更加简单:
- 使用而不是手动分割联系人信息
- 将组名与联系人存储在单独的数组属性中。您可以在“表视图数据源”部分进行切换以提取正确的数据
- 如果您确实需要使用谓词来过滤数据,并且不知道如何使用谓词语法,请使用
-(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];
}