UI:字典的两种取值的区别
字典的两种取值的区别 (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:字典的两种取值的区别的更多相关文章
- mybatis中两种取值方式?谈谈Spring框架理解?
1.mybatis中两种取值方式? 回答:Mybatis中取值方式有几种?各自区别是什么? Mybatis取值方式就是说在Mapper文件中获取service传过来的值的方法,总共有两种方式,通过 $ ...
- 牛客网Java刷题知识点之Map的两种取值方式keySet和entrySet、HashMap 、Hashtable、TreeMap、LinkedHashMap、ConcurrentHashMap 、WeakHashMap
不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...
- pig对null的处理(实际,对空文本处理为两种取值null或‘’)
pig对文本null的处理非常特殊.会处理成两种null,还会处理成''这样的空值. 比方,读name,age,sex日志信息.name取值处理,假设记录为".,,"这样,会将na ...
- map的两种取值方式
public class MapUtil{ public static void iteratorMap1(Map m) { Set set=m.keySet();//用接口实例接口 Iterator ...
- 对于String对象,可以使用"="赋值,也可以使用"new"关键字赋值,两种方式有什么区别?
当你看见这个标题的时候,你可能会下意识的去想一下,这两种方式到底有什么样的区别呢? 且看下面的demo,自然便区分开了 /** * */ package com.b510.test; /** * Pr ...
- iOS学习——UITableViewCell两种重用方法的区别
今天在开发过程中用到了UITableView,在对cell进行设置的时候,我发现对UITableViewCell的重用设置的方法有如下两种,刚开始我也不太清楚这两种之间有什么区别.直到我在使用方法二进 ...
- 网站开发进阶(六)JSP两种声明变量的区别
JSP两种声明变量的区别 在JSP中用两种声明变量的方法,一种是在<%! %>内,一种是在<% %>内.他们之间有什么区别呢?我们直接看一个JSP文件来理解. 代码如下: &l ...
- nuxt框架Universal和Spa两种render mode的区别
如下图,官网上对于Universal 和 Spa 两种render mode的区别,并没有加以说明,相信大多数人跟我一样有点懵,不知道选什么好.虽然两个模式创建的项目看不出区别. 先给出推荐选项: U ...
- Java中String对象两种赋值方式的区别
本文修改于:https://www.zhihu.com/question/29884421/answer/113785601 前言:在java中,String有两种赋值方式,第一种是通过“字面量”赋值 ...
随机推荐
- DB time实时过程分析
在我们查看awr报告的时候总是会有一个关键指标需要注意,那就是DB time,这个指标一般都是通过awr报告来看到的.比如我们得到的awr报告头部显示的下面的信息,我们就清楚的知道DB time是15 ...
- [Android] 关于系统工具栏和全屏沉浸模式
随着应用程序的一些深入设计,大家总想要更好的界面和体验,所以有些东西并不能只是知道方法就结束了,是得要去深入研究研究的.通过这个过程我觉得,从应用层面来讲,想实现一个功能很简单,但若想实现的好,就要去 ...
- mysql (master/slave)复制原理及配置
1 复制概述 Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重 ...
- 一段实现页面上的图片延时加载的js
大家如果使用firebug去查看的话就会发现,当你滚动到相应的行时,当前行的图片才即时加载的,这样子的话页面在打开只加可视区域的图片,而其它隐藏的图片则不加载,一定程序上加快了页面加载的速度,对于比较 ...
- makefile实例(2)-多个文件实例
1,源文件依赖关系 defs.h command.h buffer.h main.cpp * util.cpp * kde.cpp * * command.cpp * * display.cpp * ...
- DataTable添加列和行的三种方法
JRoger 原文 #region 方法一: DataTable tblDatas =new DataTable("Datas"); DataColumn dc =null; dc ...
- Android Application 深入分析
http://blog.csdn.net/rain_butterfly/article/details/37598939
- OpenERP中的会计凭证
OpenERP在采购和销售过程中会自动生成一些会计凭证,这些会计凭证反映了物流和资金流在财务上的处理方式. 仓库入库时 借:库存商品 贷:在途物资 收到供应商发票时 借:在途物资 借:进项税额 贷:应 ...
- Jmeter介绍
一.添加线程组 一个性能测试请求负载是基于一个线程组完成的.一个测试计划必须有一个线程组.测试计划添加线程组非常简单.在测试计划右键弹出下拉菜单(添加-->Threads(Users)---&g ...
- cmd命令 chcp
chcp是“change code page”的缩写.(关于代码页的相关知识详见:http://www.cnblogs.com/minisculestep/articles/4920992.html)