NSDictionary用于保存具有映射关系的数据。因此,NSDictionary集合里保存着两组值,一组值用于保存NSDictionary里的key,另一组值用于保存NSDictionary里的value。注意:key和value都可以是任何指针类型的数据,NSDictionary的key不允许重复
key和value之间存在一对一关系即通过指定的key,总能找到唯一的、确定的value。从NSDictionary中取出数据时,只要给出指定的key,就可以取出对应的value。NSDictionary有类似下图的结构:

所有的key组成一个NSSet集合(key没有顺序,不能重复),实际上,NSDictionary确实包含一个allKeys方法,用于返回NSDictionary所有key组成的集合,但是,NSDictionary把allKeys方法的返回值设为NSArray,说明该方法经过了进一步的转换。

NSDictionary的功能与用法

NSDictionary分别提供了类方法和实例方法来创建NSDictionary,类方法以dictionary开头,实例方法则以init开头:

  • dictionary:创建一个不包含任何key-value对的NSDictionary。
  • dictionaryWithContentsOfFile:/initWithContentsOfFile::读取指定文件的内容,使用指定的文件内容来初始化NSDictionary。该文件通常是由NSDictionary输出生成的。
  • dictionaryWithDictionary:/initWithDictionary::使用已有的NSDictionary包含的key-value对来初始化NSDictionary对象。
  • dictionaryWithObject:forKey::使用单个key-value对来创建NSDictionary对像。
  • dictionaryWithObjects:forKeys:/initWithObjects:forKeys::使用两个NSArray分别指定key、value集合,可以创建包含多个key-value对的NSDictionary。
  • dictionaryWithObjectsAndKeys:/initWithObjectsAndKeys::调用该方法时,需要按value1,key1,value2,key2,…,nil的格式传入多个key-value对。

除此之外,还可以使用如下简化语法来创建NSDictionary对象:

@{key1: value1, key2: value2, key3 ...}

常用的访问该集合的key和value的方法有:

  • count:返回所有key-value对数量。
  • allKeys:返回全部key。
  • allKeysForObject::返回指定value对应的全部key。
  • allValues:返回包含的全部value。
  • objectForKey::获取指定key对应value。
  • objectForKeyedSubscript::通过该方法的支持,允许通过下标法来获取指定key对应的value。
  • valueForKey::获取指定key对应的value。
  • keyEnumerator:返回用于遍历该NSDictionary所有key的NSEnumerator对象。
  • objectEnumerator:该方法返回用于遍历该NSDictionary所有value的NSEnumerator对象。
  • enumerateKeysAndObjectsUsingBlock::使用指定的代码块来迭代执行该集合中所有的key-value对。
  • enumerateKeysAndObjectsWithOptions:usingBlock::使用指定的代码块来迭代执行该集合中所有的key-value对。可以传入一个额外的NSEnumerationOptions参数。
  • writeToFile:atomically::将该NSDictionary对象的数据写入指定文件。

示例程序:
该程序为了能更清晰地看到key-value对的详情,为NSDictionary类扩展了一个print类别,在该类别中扩展了一个print方法,用于打印NSDictionary中key-value对的详情。
该类接口部分:

#import <Foundation/Foundation.h>@interface NSDictionary (print)
-(void) print;
@end

实现部分:

#import "NSDictionary+print.h"@implementation NSDictionary (print)
-(void) print {NSMutableString* result = [NSMutableString stringWithString:@"{"];//快速枚举法遍历//循环计数器将依次等于每个keyfor(id key in self) {[result appendString: [key description]];[result appendString:@"="];//使用下标法根据key获取对应的vakue[result appendString:[self[key] description]];[result appendString:@", "];}//获取字符串长度NSUInteger len = [result length];//去掉字符串最后两个字符[result deleteCharactersInRange:NSMakeRange(len - 2, 2)];[result appendString:@"}"];NSLog(@"%@", result);
}
@end

通过key来获取value有两种方法:

  • 调用NSDictionary的objectForKey:方法
  • 直接使用下标法

也就是说,下面两行代码的功能是相同的:

[dictionary objectForKey:key];
dictionary[key];

测试:

int main(int argc, const char * argv[]) {@autoreleasepool {NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:[[User alloc] initWithName:@"Billy" andPass:@"1234"],@"one",[[User alloc] initWithName:@"Terasa" andPass:@"2345"],@"two",[[User alloc] initWithName:@"Amy" andPass:@"3456"],@"three",[[User alloc] initWithName:@"John" andPass:@"4567"],@"four",[[User alloc] initWithName:@"Jimmy" andPass:@"5678"],@"five",nil];[dict print];NSLog(@"dict包含%ld个key-value对", [dict count]);NSLog(@"dict的所有key为:%@", [dict allKeys]);NSLog(@"<User[name=Billy,pass=1234]>对应的key为:%@",[dict allKeysForObject:[[User alloc] initWithName:@"Billy" andPass:@"1234"]]);//获取遍历dict所有value的枚举器NSEnumerator* en = [dict objectEnumerator];id value;//使用枚举器来遍历dict中所有valuewhile(value = [en nextObject]) {NSLog(@"%@", value);}//使用指定代码块来迭代执行该集合中所有的key-vakue对[dict enumerateKeysAndObjectsUsingBlock://该集合包含多少个key-value对,下面的代码块就执行相应的次数^(id key, id value, BOOL* stop) {NSLog(@"key的值为:%@",key);[value say:@"Bill"];}];}return 0;
}

输出:

{one=<User[name=Billy,pass=1234]>, five=<User[name=Jimmy,pass=5678]>, three=<User[name=Amy,pass=3456]>, two=<User[name=Terasa,pass=2345]>, four=<User[name=John,pass=4567]>}
dict包含5个key-value对
dict的所有key为:(one,five,three,two,four
)
<User[name=Billy,pass=1234]>对应的key为:(one
)
<User[name=Billy,pass=1234]>
<User[name=Jimmy,pass=5678]>
<User[name=Amy,pass=3456]>
<User[name=Terasa,pass=2345]>
<User[name=John,pass=4567]>
key的值为:one
Billy说:Bill
key的值为:five
Jimmy说:Bill
key的值为:three
Amy说:Bill
key的值为:two
Terasa说:Bill
key的值为:four
John说:Bill

对NSDictionary的key排序

方法如下:

  • keysSortedByValueUsingSelector::根据所有value指定方法的返回值对key排序;调用该方法必须返回NSOrderedAscending、NSOrderedDescending、NSOrderedSame这三个枚举值之一。
  • keysSortedByValueUsingComparator::使用指定的代码块来遍历key-value对,并根据执行结果(必须返回NSOrderedAscending、NSOrderedDescending、NSOrderedSame这三个枚举值之一)对所有key进行排序。
  • keysSortedByValueWithOptions:usingComparator::与前一个方法的功能类似,只是可以传入一个额外的NSEnumerationOptions参数。

示例程序:

#import "NSDictionary+print.h"int main(int argc, const char * argv[]) {@autoreleasepool {//NSDictionary* dict = @{@"one": @"Billy",@"two":@"Teresa",@"three":@"Amy",@"four":@"John"};//打印dict集合所有元素[dict print];//获取所有直接调用value的compare:方法对所有key进行排序//返回排序好的所有key组成的NSArrayNSArray* keyArr1 = [dict keysSortedByValueUsingSelector:@selector(compare:)];NSLog(@"%@", keyArr1);NSArray* keyArr2 = [dict keysSortedByValueUsingComparator://对value进行比较,字符串越长,即可认为value越大^(id value1, id value2){//下面定义比较大小的标准:字符串越长,即可认为value越大if([value1 length] > [value2 length]) {return NSOrderedDescending;} else if ([value1 length] < [value2 length]) {return NSOrderedAscending;} else {return NSOrderedSame;}}];NSLog(@"%@", keyArr2);//将NSDictionary的内容输出到指定文件中[dict writeToFile:@"mydict.txt" atomically: YES];}
}

先使用compare:方法排序——字符串比较大小直接根据字符对应的编码进行。后面调用代码块对value比较大小,规则是value对应的字符串越长,系统就认为该value越大。程序的输出结果为:

{one=Billy, three=Amy, two=Teresa, four=John}
(three,one,four,two
)
(three,four,one,two
)

打开 mydict.txt 文件,可以看到如下内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict><key>four</key><string>John</string><key>one</key><string>Billy</string><key>three</key><string>Amy</string><key>two</key><string>Teresa</string>
</dict>
</plist>

对NSDictionary的key进行过滤

NSDictionary还提供了方法对NSDictionary的所有key执行过滤,这些方法执行完将返回满足条件的key组成的NSSet。方法如下:

  • keysOfEntriesPassingTest::使用代码块迭代处理NSDictionary的每个key-value对。对NSDictionary的key-value对进行过滤,该代码块必须返回BOOL类型的值,只有当该代码块返回YES时,该key才会被保留下来;该代码块可以接受3个参数,其中第一个参数代表正在迭代处理的key,第二个参数代表正在迭代处理的value,第三个参数代表是否还要继续迭代,如果将第三个参数设为NO,那么该迭代会立即停止。
  • keysOfEntriesWithOptions:passingTest::该方法的功能与前一个方法的功能基本相同。只是该方法可以额外传入一个附加的NSEnumerationOptions选项参数。

如下程序示范了对NSDictionary进行过滤。

#import "NSDictionary+print.h"
int main(int argc, const char * argv[]) {@autoreleasepool {NSDictionary* dict = @{@"Billy":[NSNumber numberWithInt: 89],@"Teresa":[NSNumber numberWithInt: 69],@"Amy":[NSNumber numberWithInt: 78],@"John":[NSNumber numberWithInt: 109]};[dict print];//对NSDictionary的所有key进行过滤NSSet* keySet = [dict keysOfEntriesPassingTest://使用代码块对NSDictionary的key-value对进行过滤^(id key, id value, BOOL* stop) {//当value的值大于80时返回YES//这意味着只有value的值大于80的key才会被保存下来return (BOOL)([value intValue] > 80);}];NSLog(@"%@", keySet);}
}

输出:

{John=109, Billy=89, Amy=78, Teresa=69}
{(Billy,John
)}

使用自定义类作为NSDictionary的key

如果程序打算使用自定义类作为NSDictionary的key,则该自定义类必须满足如下需求:

  • 该自定义类正确重写过isEqual: 和hash方法。所谓正确重写,是指当两个对象通过isEqual:方法判断相等时,两个对象的hash方法返回值也相等。
  • 该自定义类必须实现了copyWithZone:方法,该方法最好返回该对象的不可变副本。

为什么要实现copyWithZone:方法呢?因为对于NSDictionary来说,key是非常关键的,NSDictionary需要根据key来访问value——从这个意义上看,key相当于NSDictionary的索引,如果key本身是可变的,且程序可以通过其他变量来修改NSDictionary的key,这就可能导致NSDictionary的“索引”值被破坏,从而导致NSDictionary的完整性被破坏。
为了让前面的User类作为NSDictionary的key,还需要让该User类实现NSCopying协议(可选的,通常建议实现),并让该User类实现copyWithZone:方法。User实现的copyWithZone:方法如下:

-(id) copyWithZone: (NSZone*) zone {NSLog(@"--正在复制--");//复制一个对象User* newUser = [[[self class] allocWithZone:zone] init];//将被复制的对象的实例变量的值赋给新对象的实例变量newUser->_name = _name;newUser->_pass = _pass;return newUser;
}

User.h:

#import <Foundation/Foundation.h>@interface User : NSObject@property (nonatomic, copy) NSString* name;
@property (nonatomic, copy) NSString* pass;
-(id) initWithName: (NSString*) aName andPass: (NSString*) aPass;
-(void) say: (NSString*) content;@end

User.m:

#import "User.h"@implementation User-(id) initWithName:(NSString *) name andPass:(NSString *) pass {if (self = [super init]) {self->_name = name;self->_pass = pass;}return self;
}
-(void) say: (NSString*) content {NSLog(@"%@说:%@",self.name, content);
}
//重写isEqual: 方法,重写比较方法为
//如果两个User的name、pass相等,既可以认为它们相等
-(BOOL) isEqual: (id) other {if(self == other) {return YES;}if([other class] == User.class) {User* target = (User*) other;return [self.name isEqualToString: target.name] && [self.pass isEqualToString: target.pass];}return NO;
}
//重写description方法,可以看到User状态
-(NSString*) description {return [NSString stringWithFormat:@"<User[name=%@,pass=%@]>", self.name, self.pass];
}
-(NSUInteger) hash {NSLog(@"===hash===");NSUInteger nameHash = self.name == nil ? 0 : [self.name hash];NSUInteger passHash = self.pass == nil ? 0 : [self.pass hash];return nameHash *31 + passHash;
}
-(id) copyWithZone: (NSZone*) zone {NSLog(@"--正在复制--");//复制一个对象User* newUser = [[[self class] allocWithZone:zone] init];//将被复制的对象的实例变量的值赋给新对象的实例变量newUser->_name = _name;newUser->_pass = _pass;return newUser;
}
@end

主函数:

#import "User.h"
#import "NSDictionary+print.h"int main(int argc, const char * argv[]) {@autoreleasepool {User* u1 = [[User alloc] initWithName:@"Billy" andPass:@"765"];NSDictionary* dict = @{[[User alloc] initWithName:@"Bill" andPass:@"123"]:@"one",u1:@"two",[[User alloc] initWithName:@"Bill" andPass:@"123"]:@"three",[[User alloc] initWithName:@"Nick" andPass:@"890"]:@"four",[[User alloc] initWithName:@"Polly" andPass:@"761"]:@"five"};//将u1的密码设为nilu1.pass = nil;//由于NSDictionary并未直接使用u1所指的User作为key//而是先复制了u1所指向对象的副本,然后以该副本作为key//因此程序将看到dict的key不会受到任何影响[dict print];}
}

当程序尝试使用任何对象作为key时,会先调用copy方法来复制该key的不可变副本,实际是以该副本作为NSDictionary的key。因此,上面程序对u1的pass进行修改时,NSDictionary的所有key并不会受到任何影响。
输出结果:

===hash===
--正在复制--
===hash===
--正在复制--
===hash===
===hash===
--正在复制--
===hash===
--正在复制--
===hash===
===hash===
===hash===
===hash===
{<User[name=Bill,pass=123]>=one, <User[name=Billy,pass=765]>=two, <User[name=Polly,pass=761]>=five, <User[name=Nick,pass=890]>=four}

其中两个User对象的name、pass完全相同,但这两个对象通过isEqual:方法会返回YES,并且hash方法返回值也相等,因此只会保留一个。

NSMutableDictionary的功能与用法

NSMutableDictionary继承了NSDictionary,它代表一个key-value对可变的NSDictionary集合。由于NSMutableDictionary可以动态地添加key-value对,因此,创建NSMutableDictionary集合时可以指定初始容量。
NSMutableDictionary主要新增了如下方法:

  • setObject:forKey::设置一个key-value对。如果NSDictionary中没有包含与该key相同的key-value对,那么NSDictionary将会新增一个key-value对;否则该key-value对将覆盖已有的key-value对。
  • setObject:forKeyedSubscript::通过该方法的支持,允许程序通过下标法来设置key-value对。
  • addEntriesFromDictionary::将另一个NSDictionary中所有的key-value对复制到当前NSDictionary中。
  • setDictionary::用另一个NSDictionary中所有的key-value对替换当前NSDictionary中的key-value对。
  • removeObjectForKey::根据key来删除key-value对。
  • removeAllObjects:清空该NSDictionary。
  • removeObjectsForKeys::使用多个key组成的NSArray作为参数,同时删除多个key对应的key-value对。

示范程序:

int main(int argc, const char * argv[]) {@autoreleasepool {//使用单个key-value对来创建NSMutable Dictionary对象NSMutableDictionary* dict = [NSMutableDictionarydictionaryWithObjectsAndKeys:[NSNumber numberWithInt:89],@"Billy", nil];//使用下标法设置key-value对。由于NSDictionary中已经存在该key//因此此处设置的value会覆盖前面的valuedict[@"Billy"] = [NSNumber numberWithInt:99];[dict print];NSLog(@"再次添加key-value对");dict[@"Amy"] = [NSNumber numberWithInt: 67];[dict print];NSDictionary* dict2 = [NSDictionarydictionaryWithObjectsAndKeys:[NSNumber numberWithInt:79],@"Amy",[NSNumber numberWithInt:86],@"Takumi",[NSNumber numberWithInt:12],@"Jimmy",nil];//将另一个NSDictionary中的key-value对添加到当前NSDictionary中[dict addEntriesFromDictionary: dict2];[dict print];//根据key来删除key-value对[dict removeObjectForKey:@"Takumi"];[dict print];//同时删除多个key对应的key-value对[dict removeObjectsForKeys:[NSArray arrayWithObjects:@"Amy",@"Billy", nil]];[dict print];}
}

输出:

{Billy=99}
再次添加key-value对
{Billy=99, Amy=67}
{Jimmy=12, Billy=99, Takumi=86, Amy=79}
{Jimmy=12, Billy=99, Amy=79}
{Jimmy=12}

OC Foundation框架 字典相关推荐

  1. iOS - OC Foundation 框架

    前言 框架是由许多类.方法.函数和文档按照一定的逻辑组织起来的集合,以使研发程序更容易. Foundation 框架:为所有程序开发奠定基础的框架称为 Foundation 框架. Cocoa :是指 ...

  2. OC Foundation框架—字符串

    一.Foundation框架中一些常用的类 字符串型: NSString:不可变字符串 NSMutableString:可变字符串 集合型: 1) NSArray:OC不可变数组 NSMutableA ...

  3. [OC Foundation框架 - 9] NSMutableArray

    可变的NSArray,可以随意添加OC对象 1.创建 1 void arrayCreate()2 {3 NSMutableArray *array = [NSMutableArray arrayWit ...

  4. (转载)OC学习篇之---Foundation框架中的NSDirctionary类以及NSMutableDirctionary类

    昨天学习了Foundation框架中NSArray类和NSMutableArray类,今天来看一下Foundation框架中的NSDirctionary类,NSMutableDirctionary类, ...

  5. OC高级foundation框架类以及数据的简单存储

    Objective-c高级复习 第一章 Foundation框架介绍 Foundation.framework是iOS开发的核心框架之 第二章 一.NSNumber OC的数字类型(存储C语言中简单的 ...

  6. 黑马程序员——OC基础05—Foundation框架

    --Java培训.Android培训.iOS培训..Net培训.期待与您交流! --- 一.Foundation框架 1.Foundation就是类.方法.函数.文档等按照一定的逻辑组织起来的集合., ...

  7. 黑马程序员--OC之Foundation框架的使用

    黑马程序员--OC之Foundation框架的使用 ------- <a href="http://www.itheima.com" target="blank&q ...

  8. [黑马IOS自学第十四篇]Foundation框架学习

    框架:由许多类,方法,函数和文档按照一定逻辑组织起来的集合 不小心修改了系统的文件,引起的错误 #import<Foundation/Foundation.h>int main(intar ...

  9. 黑马程序员——零基础学习iOS开发——13 Foundation框架

    ------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS ...

  10. 苹果Foundation框架视频课程-关东升-专题视频课程

    苹果Foundation框架视频课程-8731人已学习 课程介绍         Foundation是OS X和iOS应用程序开发的基础框架.Swift和Objective-C语言都可以使用Foun ...

最新文章

  1. jvm四:常量的本质含义以及助记符基本认识
  2. 几种搜索引擎算法的研究
  3. mysql怎么升级_MySQL UPDATE 更新
  4. VTK:几何对象之PlaneSource
  5. 文件服务器定时开关机,如何配置作服务器定时开关机.ppt
  6. 25.智能指针.rs
  7. Django学习手册 - 前端input数据获取
  8. Linux单用户下提示权限不够,Linux_/dev/null 权限不足,/dev/null文件设备的权限不对, - phpStudy...
  9. Serializable中的serialVersionUID
  10. FragmentSharedFabTransition
  11. 等比数列求和(递归)
  12. LAMP环境的搭建与部署
  13. OpenCASCADE:Qt OCCT 概览示例
  14. vue run dev报错 缺少package.json文件
  15. P02014080杨臣----周五信息论课程回答作业
  16. linux物料管理,SAP-PM 工具管理篇之出入库
  17. 怎么用svg画一个圆圈(一)
  18. 程序员的12条经营分享
  19. 五子棋游戏AI智能算法设计
  20. oracle 删除字段方法 alter table set unused

热门文章

  1. Dwz 国产框架 JUI 分页组件下拉菜单bug解决方案
  2. 数据结构 严薇敏 单链表(无头结点)的实现(增 删 改 查)及其使用方法详解
  3. 计算机毕业设计Android的计算器app设计(源码+系统+mysql数据库+Lw文档)
  4. 汽车诊断协议:K线/CAN线、kwp2000、ISO14230、ISO1575、SAEJ1939
  5. 编程实践(Pandas)Task08
  6. wifi连接一段时间才能上网_为什么wifi连接上却不能上网?教你如何解决wifi连上却不能上网...
  7. php注册账号绑定微信,PHP-微信公众账号中的一键绑定该怎么设计
  8. 完美世界3D格斗手游[格斗宝贝]今日公测
  9. python大众点评霸王餐_如何抽中大众点评霸王餐?
  10. 基于51单片机的火灾报警系统仿真