字典的两种取值的区别 (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(, , , );
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 == ) {
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] == ) {
[_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":@"",@"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 == ) {
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(, )];
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 ;
}
#pragma mark---cell行高
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return ;
}
#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

代码

UI:字典的两种取值的区别的更多相关文章

  1. mybatis中两种取值方式?谈谈Spring框架理解?

    1.mybatis中两种取值方式? 回答:Mybatis中取值方式有几种?各自区别是什么? Mybatis取值方式就是说在Mapper文件中获取service传过来的值的方法,总共有两种方式,通过 $ ...

  2. 牛客网Java刷题知识点之Map的两种取值方式keySet和entrySet、HashMap 、Hashtable、TreeMap、LinkedHashMap、ConcurrentHashMap 、WeakHashMap

    不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...

  3. pig对null的处理(实际,对空文本处理为两种取值null或‘’)

    pig对文本null的处理非常特殊.会处理成两种null,还会处理成''这样的空值. 比方,读name,age,sex日志信息.name取值处理,假设记录为".,,"这样,会将na ...

  4. map的两种取值方式

    public class MapUtil{ public static void iteratorMap1(Map m) { Set set=m.keySet();//用接口实例接口 Iterator ...

  5. 对于String对象,可以使用"="赋值,也可以使用"new"关键字赋值,两种方式有什么区别?

    当你看见这个标题的时候,你可能会下意识的去想一下,这两种方式到底有什么样的区别呢? 且看下面的demo,自然便区分开了 /** * */ package com.b510.test; /** * Pr ...

  6. iOS学习——UITableViewCell两种重用方法的区别

    今天在开发过程中用到了UITableView,在对cell进行设置的时候,我发现对UITableViewCell的重用设置的方法有如下两种,刚开始我也不太清楚这两种之间有什么区别.直到我在使用方法二进 ...

  7. 网站开发进阶(六)JSP两种声明变量的区别

    JSP两种声明变量的区别 在JSP中用两种声明变量的方法,一种是在<%! %>内,一种是在<% %>内.他们之间有什么区别呢?我们直接看一个JSP文件来理解. 代码如下: &l ...

  8. nuxt框架Universal和Spa两种render mode的区别

    如下图,官网上对于Universal 和 Spa 两种render mode的区别,并没有加以说明,相信大多数人跟我一样有点懵,不知道选什么好.虽然两个模式创建的项目看不出区别. 先给出推荐选项: U ...

  9. Java中String对象两种赋值方式的区别

    本文修改于:https://www.zhihu.com/question/29884421/answer/113785601 前言:在java中,String有两种赋值方式,第一种是通过“字面量”赋值 ...

随机推荐

  1. T-SQL备忘(4):分页

    set statistics io on set statistics time on --SQL Server 2012分页方式 select * from Production.Product o ...

  2. Informatica9.6.1在Linux Red Hat 5.8上安装遇到的有关问题整理_3

    3.Repository Service启动后的页面编码问题 1)错误信息: 2)原因分析及解决步骤 原因分析: informatica产品安装背后AdminConsole的Code page默认为U ...

  3. swfupload 参数说明

    一.配置参数对象中的常用属性及说明 属性 类型 默认值 描述 upload_url String   处理上传文件的服务器端页面的url地址,可以是绝对地址,也可以是相对地址,当为相对地址时相对的是当 ...

  4. Windows执行打开文件命令

    ShellExecute(NULL, "open",  localFile.c_str(),  NULL, NULL, SW_SHOW);          会调用该文件类型关联的 ...

  5. js中document.all 的用法

    1. document.all是什么? document.all 实质就是文档中所有元素的集合.可以看做一个数组.   2.document.all怎么用? 2.1 根据下标取元素. 语法: docu ...

  6. Spring依赖注入 --- 简单使用说明

    Spring依赖注入 --- 简单使用说明 本文将对spring依赖注入的使用做简单的说明,enjoy your time! 1.使用Spring提供的依赖注入 对spring依赖注入的实现方法感兴趣 ...

  7. html --- VML --- javascript --- 旋转矩形

    矢量标记语言 --- Vector Markup Language 运行它的代码需要打开IE的兼容性视图 如有疑问请参考:http://msdn.microsoft.com/en-us/library ...

  8. 用代码将Excel数据导入Sql Server

    这里直接用小例子说明. 1.打开VS2010—>文件—>新建—>网站,选择ASP.NET空网站并设置存放路径以创建空网站.(我这里路径设置为D:\excelEduceToSql) 2 ...

  9. Axure rp 基础知识 转

    首先做个声明:此次教程里为了快速完成,借用了一些网上已有教程的图文,不是剽窃,只图方便.另外,因为汉化版本可能功能名称等略有差别,请自行理解. 名词解释: 线框图:一般就是指产品原型,比如:把线框图尽 ...

  10. the NTP socket is in use, exiting

    centos下使用如下命令手动同步服务器时间 ntpdate ntp.fudan.edu.cn 或 ntpdate ntp.api.bz 出现“the NTP socket is in use, ex ...