字典的两种取值的区别 (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. LA 3635 Pie 派 NWERC 2006

    有 f + 1 个人来分 n 个圆形派,每个人得到的必须是一整块派,而不是几块拼在一起,并且面积要相同.求每个人最多能得到多大面积的派(不必是圆形). 这题很好做,使用二分法就OK. 首先在读取所有派 ...

  2. Linux/Unix shell 自动发送AWR report

    观察Oracle数据库性能,Oracle自带的awr 功能为我们提供了一个近乎完美的解决方案,通过awr特性我们可以随时从数据库提取awr报告.不过awrrpt.sql脚本执行时需要我们提供一些交互信 ...

  3. Hadoop学习总结之五:Hadoop的运行痕迹

    Hadoop学习总结之五:Hadoop的运行痕迹   Hadoop 学习总结之一:HDFS简介 Hadoop学习总结之二:HDFS读写过程解析 Hadoop学习总结之三:Map-Reduce入门 Ha ...

  4. jQuery 实现Bootstrap Chart 图表

    很多时候我们制作报表的时候需要图表,如果你使用bootstrap开发你的网站,如果你需要使用图表,那么最简单的方法就是就是使用bootstrap 的chart.js来实现图表,下面介绍方法 1.引入c ...

  5. AndroidSdk离线下载

    http://dl.vmall.com/c00x42abt3# 关键字:android sdk 离线

  6. 【Linux】一个简单的线程创建和同步的例子

    最近很多精力在Linux上,今天简单看了一下Linux上的线程和同步,其实不管windows还是Linux,OS层面的很多原理和概念都是相同的,很多windows之上的经验和概念完全可以移植到Linu ...

  7. nagios监控linux设置

    本章主要用来设置nagios的相关配置文件,从而能实现对linux系统的监控. 在进行监控相关服务的时候,nagios会周期性的调用插件去监测服务器的状态,nagios自带的所有插件都放在如下目录: ...

  8. 【LeetCode】7 & 8 - Reverse Integer & String to Integer (atoi)

    7 - Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 Notic ...

  9. IT智力题

    题目1:你让工人为你工作7天,给工人的回报是一根金条.金条平分成相连的7段,你必须在每天结束时给他们一段金条,如果只许你两次把金条弄断,你 如何给你的工人付费? 答案:两次弄断就应分成三份,我把金条分 ...

  10. 编写服务说明.thrift文件

    1.数据类型 基本类型: bool:布尔值,true 或 false,对应 Java 的 boolean byte:8 位有符号整数,对应 Java 的 byte i16:16 位有符号整数,对应 J ...