关于OC中用字典添加联系人到通讯录中常见的错误
情景案例:根据联系人的姓名的首字母进行分组,将首字母同为A的放在同一个数组中,以此类推。
首先关于这个情景,我们很有可能想到将字典的key值设置为A到Z的26个字母,然后我们进行添加的时候直接根据key值来添加。(这种做法虽然看上去比较繁琐,但是有益于理解,个人不是很推荐)
- (void)addPeople:(People *)people
{
NSMutableArray *key = [NSMutableArray arrayWithObjects:@"A",@"B",@"C",@"D",@"E",@"F",@"G",@"H",@"I",@"J",@"K",@"L",@"M",@"N",@"O",@"P",@"Q",@"R",@"S",@"T",@"U",@"V",@"W",@"X",@"Y",@"Z",nil];
NSMutableArray *AllValue = [NSMutableArray array];
for (int i = 0; i < 26; i ++) {
NSMutableArray *EachValue = [NSMutableArray array];
[AllValue addObject:EachValue];
}
_dictionary = [[NSMutableDictionary alloc]initWithObjects:AllValue forKeys:key];
[[_dictionary objectForKey:people.group] addObject:people];
}
这种写法很繁琐 ,先要创建三种数组,一个存放key值的数组还有一个是每个key值对应的数组(这里用for循环26次),还有一个是Value大数组包含26个小数组。这时候对应的key值添加对象就不存在覆盖前面一个相同key值的情形。
错误点:不理解字典的定义导致的错误
我们都知道字典中的key是唯一不重复存在,我们在进行添加的时候不能够根据字典的key直接在对应的value上添加people类的对象。
- (void)addPeople:(People *)people
{
[_dictionary setObject:people forKey:people.group];
NSLog(@"===============添加成功===============");
}
很显然这样做的后果就是:在可变字典中后面一个相同的key值后覆盖前面一个相同key的value。
下面这种做法是优化之后的,传入什么姓名分组再在字典中开辟对应的键值对
- (void)addPeople:(People *)people
{
BOOL ishave = NO;
if (people.name != nil && people.telephone != nil)
{
for (NSString *k in _dictionary) {
if (k == people.group) {
NSMutableArray *p = [NSMutableArray array];
p = [_dictionary objectForKey:k];
[p addObject:people];
ishave = YES;
}
}
if (!ishave) {
NSMutableArray *p = [NSMutableArray array];
[_dictionary setObject: p forKey: people.group];
[p addObject:people];
}
NSLog(@"===========添加联系人成功=============");
}else
{
NSLog(@"===========添加联系人失败=============");
}
}
这片代码首先我们先判断联系人的name和telephone是否为空,如果为空,直接打印失败。
其次,我们要对可变字典中的key进行遍历,如果key中有和联系人分组(首字母)相同时,我们只需要将people类的对象直接添加到对应的value里面。
不然,我们需要创建一个可变数组用来对应不存在的分组,然后将这个对象添加到可变数组中。
但是,我发现在下面对分组里面的姓名进行排序时,我用点语法调用name竟然系统提示我没有声明name的属性。附上图:
报的错提示是:Property ‘name’ not found on object of type ‘id’ ## 标题 ##
更正说明:
上述问题解决方案:如果需要使用点语法,需要将数组中的元素强装成People类型就直接使用name属性了