字典的两种取值的区别 (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. RNN 与 LSTM 的应用

    之前已经介绍过关于 Recurrent Neural Nnetwork 与 Long Short-Trem Memory 的网络结构与参数求解算法( 递归神经网络(Recurrent Neural N ...

  2. HDU 1015 Safecracker

    解题思路:这题相当诡异,样例没过,交了,A了,呵呵,因为理论上是可以通过的,所以 我交了一发,然后就神奇的过了.首先要看懂题目. #include<cstdio> #include< ...

  3. Intent七大属性

    一.Intent的作用是什么?    1.Intent 用于封装程序的”调用意图“.两个Activity之间,可以把需要交换的数据封装成Bundle对象,然后使用Intent携带Bundle对象,实现 ...

  4. oracle 组函数

    一.组函数嵌套 ORACLE中规定,组函数嵌套只能嵌两层.其实多层嵌套并没有实际的用途,因此ORACLE没有提供组函数的多层嵌套.但是,单行函数是可以多层嵌套的. 二. 1.Oracle包含以下组函数 ...

  5. 【转】linux打包压缩命令

    转自:http://www.cnblogs.com/end/archive/2011/04/20/2022614.html tar命令 [root@linux ~]# tar [-cxtzjvfpPN ...

  6. 选择下拉列表最大索引值 Select From List By Max Index

    Select是网页表单中较为常见的元素,在Selenium2Library 中也有相应关键字可以操作,比如: (1)通过指定索引选择 Name: Select From List By Index   ...

  7. java 多线程同步

    一.synchronized关键字 同步方法 每个对象都包含一把锁(也叫做监视器),它自动称为对象的一部分(不必为此写任何特殊的代码).调用任何synchronized方法时,对象就会被锁定,不可再调 ...

  8. js document对象

    document对象可以通过多种方式获取: 最常见的一种情况是,你在文档的script脚本中直接使用document,这个document代表运行着该脚本的文档.(这个document和window. ...

  9. css3 --- 翻页动画 --- javascript --- 3d --- Action

    用css3和javascript做一个翻页动画<Action> 如有疑问请参照我的上一篇随笔:http://www.cnblogs.com/kodoyang/p/Html_Css3_Car ...

  10. multi-catch和try-catch异常处理

    multi-catch属于JDK1.7之后出现的,举例如下: class FactoryTest { public static Fruits getInstance(String className ...