字典的两种取值的区别 (objectForKey: 和 valueForKey )参考
一般来说 key 可以是任意字符串组合,如果 key 不是以 @ 符号开头,这时候 valueForKey: 等同于 objectForKey:,如果是以 @ 开头,去掉 key 里的 @ 然后用剩下部分作为 key 执行 [super valueForKey:]。
比如:
NSDictionary *dict = [NSDictionary dictionaryWithObject:@"theValue"
forKey:@"theKey"];
NSString *value1 = [dict objectForKey:@"theKey"];
NSString *value2 = [dict valueForKey:@"theKey"];
这时候 value1 和 value2 是一样的结果。如果是这样一个 dict:
NSDictionary *dict = [NSDictionary dictionaryWithObject:@"theValue"
forKey:@"@theKey"];// 注意这个 key 是以 @ 开头
NSString *value1 = [dict objectForKey:@"@theKey"];
NSString *value2 = [dict valueForKey:@"@theKey"];
value1 可以正确取值,但是 value2 取值会直接 crash 掉,报错信息:
Terminating app due to uncaught exception ‘NSUnknownKeyException’, reason: ‘[<__NSCFDictionary 0x892fd80> valueForUndefinedKey:]: this class is not key value coding-compliant for the key theKey.’
这是因为 valueForKey: 是 KVC(NSKeyValueCoding) 的方法,在 KVC 里可以通过 property 同名字符串来获取对应的值。比如:
@interface Person : NSObject
@property (nonatomic, retain) NSString *name;
@end
...
Person *person = [[Person alloc] init];
person.name = @"fannheyward";
NSLog(@"name:%@", [person name]);
//name:fannheyward
NSLog(@"name:%@", [person valueForKey:@"name"]);
//name:fannheyward
[person release];
valueForKey: 取值是找和指定 key 同名的 property accessor,没有的时候执行 valueForUndefinedKey:,而 valueForUndefinedKey: 的默认实现是抛出 NSUndefinedKeyException 异常。
回过头来看刚才 crash 的例子, [dict valueForKey:@"@theKey"]; 会把 key 里的 @ 去掉,也就变成了 [dict valueForKey:@"theKey"];,而 dict 不存在 theKey 这样的 property,转而执行 [dict valueForUndefinedKey:@"theKey"];,抛出 NSUndefinedKeyException 异常后 crash 掉。
objectForKey: 和 valueForKey: 在多数情况下都是一样的结果返回,但是如果 key 是以 @ 开头,valueForKey: 就成了一个大坑,建议在 NSDictionary 下只用 objectForKey: 来取值。
修改导航栏的背景颜色:参考
修改tableView 的右侧的索引的颜色:参考
更改索引的背景颜色:
self.tableView.sectionIndexBackgroundColor = [UIColor clearColor];
更改索引的文字颜色:
self.tableView.sectionIndexColor = [UIColor blueColor];
tableview 的系统自带的编辑按钮的修改 参考
// // RootViewController.m // 13 // // Created by lanounjw on 15/9/13. // Copyright (c) 2015年 lanouhn. All rights reserved. // #import "RootViewController.h" #import "Contacts.h" #import "ContactCell.h" #import "UIImage+Scale.h" #import "macroHeader.h" @interface RootViewController ()<UITableViewDataSource,UITableViewDelegate> @property(nonatomic,retain)NSMutableDictionary * dataDic; @property(nonatomic,retain)NSMutableArray * sortedKey; @property(nonatomic,retain)Contacts * per; @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; [self customerNavBar]; [self readFromLoca]; //创建 tableView UITableView * tableview = [[UITableView alloc]initWithFrame:[[UIScreen mainScreen]bounds] style:UITableViewStylePlain]; tableview.separatorColor = [UIColor grayColor]; tableview.separatorInset = UIEdgeInsetsMake(0, 10, 0, 10); tableview.dataSource = self; tableview.delegate = self; //更改索引的背景颜色: tableview.sectionIndexBackgroundColor = [UIColor clearColor]; //更改索引的文字颜色: tableview.sectionIndexColor = UIColorFromHex(0x66CDAA); self.view = tableview; [tableview release]; } -(void)customerNavBar{ self.navigationItem.title = @"zzs150739"; UIBarButtonItem * left = [[UIBarButtonItem alloc]initWithImage:[[UIImage imageNamed:@"add_contact@2x"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:self action:@selector(handleNewContact:)]; self.navigationItem.leftBarButtonItem = left; [left release]; self.navigationController.navigationBar.barTintColor = UIColorFromHex(0x66CDAA); #pragma mark---添加自带的编辑按钮 self.editButtonItem.title = @"编辑"; self.navigationItem.rightBarButtonItem = self.editButtonItem; self.editButtonItem.tintColor = [UIColor whiteColor]; } #pragma mark---添加自带的编辑按钮后重写编辑的方法 -(void)setEditing:(BOOL)editing animated:(BOOL)animated{ [super setEditing:editing animated:animated]; [(UITableView *)self.view setEditing:editing animated:YES]; if (self.editing) { self.editButtonItem.title = @"完成"; }else{ self.editButtonItem.title = @"修改"; } } #pragma mark---设置某些区域可以被修改 -(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{ if (indexPath.row == 0) { return YES;//NO 就是不能被修改 } return YES; } #pragma mark---提交编辑状态 //处理数据以及页面(真正的数据是放在字典或者集合里) -(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{ NSString * key = [self.sortedKey objectAtIndex:indexPath.section]; NSMutableArray * group = [_dataDic objectForKey:key]; Contacts * contact = [group objectAtIndex:indexPath.row]; if (editingStyle == UITableViewCellEditingStyleDelete) { if ([group count] == 1) { [_dataDic removeObjectForKey:key]; [_sortedKey removeObject:key]; [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationBottom]; }else{ [group removeObject:contact]; [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft]; } }else{ NSDictionary * dic = @{@"name":@"白白",@"gender":@"男",@"phoneNum":@"13523526303",@"photo":@"oooo"}; Contacts * newPer = [[Contacts alloc]initWithDic:dic]; [group insertObject:newPer atIndex:indexPath.row]; [tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight]; [newPer release]; } } #pragma mark---tableView 的 cell 的移动 -(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{ return YES; } #pragma mark---提交移动后的结果 -(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{ NSString * key = [self.sortedKey objectAtIndex:sourceIndexPath.section]; NSMutableArray * group = [self.dataDic objectForKey:key]; Contacts * per = [[group objectAtIndex:sourceIndexPath.row]retain]; [group removeObjectAtIndex:sourceIndexPath.row]; [group insertObject:per atIndex:destinationIndexPath.row]; [per release]; } #pragma mark---限定 cell 的移动界限,禁止跨区运动 -(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath{ if (sourceIndexPath.section == proposedDestinationIndexPath.section) { return proposedDestinationIndexPath; }else{ return sourceIndexPath; } } #pragma mark---修改删除按钮的文字 -(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{ return @"删除"; } #pragma mark---tableview的 cell 的编辑样式 -(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{ if (indexPath.section == 0) { return UITableViewCellEditingStyleInsert; } return UITableViewCellEditingStyleDelete; } #pragma mark--- #pragma mark---添加联系人页面 -(void)handleNewContact:(UIBarButtonItem *)sender{ //添加联系人 } #pragma mark---读取本地数据 -(void)readFromLoca{ NSString * filePath = [[NSBundle mainBundle]pathForResource:@"contacts" ofType:@"plist"]; self.dataDic = [NSMutableDictionary dictionaryWithContentsOfFile:filePath]; NSDictionary * dic = [NSDictionary dictionaryWithDictionary:_dataDic]; NSArray * sorted = [[dic allKeys]sortedArrayUsingSelector:@selector(compare:)]; self.sortedKey = [NSMutableArray arrayWithArray:sorted]; for (NSString * key in self.sortedKey) { NSMutableArray * contactArr = [NSMutableArray array]; NSArray * group = [NSArray arrayWithArray:[_dataDic objectForKey:key]]; for (NSDictionary * dic in group) { Contacts * per = [[Contacts alloc]initWithDic:dic]; [contactArr addObject:per]; } [self.dataDic setObject:contactArr forKey:key]; } } #pragma mark ---2个必须实现的方法 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return [[self.dataDic objectForKey:self.sortedKey[section]] count]; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString * identifier = @"cell"; ContactCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; if (!cell) { cell = [[ContactCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier]; } NSString * key = [self.sortedKey objectAtIndex:indexPath.section]; NSArray * group = [self.dataDic objectForKey:key]; Contacts * contact = [group objectAtIndex:indexPath.row]; self.per = contact; cell.nameLabel.text = _per.name; cell.photoView.image = [[UIImage imageNamed:_per.photo] setScaleTOSize:CGSizeMake(50, 50)]; cell.contentLabel.text = _per.phoneNum; return cell; } #pragma mark---右侧索引 -(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{ NSArray * arr = [[self.dataDic allKeys]sortedArrayUsingSelector:@selector(compare:)]; return arr; } #pragma mark---标题页面 -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ NSString * titleName = self.sortedKey[section]; return titleName; } #pragma mark---页眉行高 -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ return 40; } #pragma mark---cell行高 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 90; } #pragma mark---分区数目 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return [[self.dataDic allKeys] count]; } #pragma mark---内存警告 - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; if ([self isViewLoaded] && !self.view.window) { self.view = nil; } } @end