【IOS 开发学习总结-OC-31】★★OC之foundation 框架——字典(NSDictionary 与 NSMutableDictionary)
2015-10-05 08:58
741 查看
NSDictionary用于保存具有映射关系的数据。NSDictionary集合保存了2组值——一组存 key, 一组存 value。
value与 key 都可以是任何引用类型的数据。Map 的 key 不允许重复。value与 key存在但相向一对一的关系。一个 key 对应唯一的一个 value.
1.
2.
3.
4.
5.
6.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
示例代码:
FKUser.h
FKUser.m
NSDictionary+print.h
NSDictionary+print.m
通过 key 来获取 value 有2种语法(2种方法功能相同):
NSDictionaryTest.m
编译运行结果:
1.
2.
3.
示例程序(用的是前面的类别文件):
编译运行结果:
1.
示例代码:
NSDictionaryFilter.m
编译运行结果:
- 该自定义类正确重写过
- 该自定义 类必须实现了
在FKUser.m 文件中实现
test.m
编译运行 结果;
1.
2.
3.
4.
5.
6.
7.
示例代码段 :
value与 key 都可以是任何引用类型的数据。Map 的 key 不允许重复。value与 key存在但相向一对一的关系。一个 key 对应唯一的一个 value.
NSDictionary的功能与用法
NSDictionary的创建同样有类方法和实例方法。以 dictionary 开头的是类方法,以 init 开头的是实例方法。创建NSDictionary对象的几类常见方法:
创建NSDictionary对象的几类常见方法:1.
dictionary:——创建一个不包含任何 key-value 对的NSDictionary
2.
dictionaryWithContentsOfFile:/initWithContentsOfFile:——读取指定文件的内容来初始化NSDictionary(该文件通常是由NSDictionary自己输出生成)
3.
dictionaryWithDictionary:/initWithDictionary:——用已有的包含 key-value 对 来初始化NSDictionary对象
4.
dictionaryWithObject: forKey:——用单个key-value 对 创建NSDictionary对象
5.
dictionaryWithObjects:<#(nonnull NSArray *)#> forKeys:<#(nonnull NSArray<id<NSCopying>> *)#>——使用2个NSArray分别指定 key,value 集合,可以创建多组key-value 对的NSDictionary。
6.
dictionaryWithObjectsAndKeys:——按 value1,key1,value2,key2,……nil 的格式传入多个键值对。
得到NSDictionary对象后,如何访问该集合包含的 key 或 value 呢?
得到NSDictionary对象后,如何访问该集合包含的 key 或 value 呢?1.
count:——返回NSDictionary包含的键值对的数量
2.
allKeys:——返回NSDictionary包含的全部 key.
3.
allKeysForObject:——返回指定 value 对应的所有 key
4.
allValues:——返回NSDictionary包含的全部 value
5.
objectForKey:——获取该NSDictionary中指定 key 对应的 value
6.
objectForKeyedSubscript:——通过该方法,允许NSDictionary通过下标法来获取指定 key 对应的 value
7.
valueForKey:——获取该NSDictionary中指定 key 对应的 value
8.
keyEnumerator:——返回用于遍历该NSDictionary所有key 的 NSEnumerator对象。
9.
objectEnumerator:————返回用于遍历该NSDictionary所有value 的 NSEnumerator对象。
10.
enumerateKeysAndObjectsUsingBlock:——使用代码块,来迭代执行该集合中所有的 键值对。
11.
enumerateKeysAndObjectsWithOptions:<#(NSEnumerationOptions)#> usingBlock:————使用代码块,来迭代执行该集合中所有的 键值对,该方法可以传入一个额外得到 option参数
12.
writeToFile:<#(nonnull NSString *)#> atomically:<#(BOOL)#>——将该字典对象的数据写入指定文件。
示例代码:
FKUser.h
#import <Foundation/Foundation.h> @interface FKUser : NSObject @property (nonatomic , copy) NSString* name; @property (nonatomic , copy) NSString* pass; - (id) initWithName:(NSString*) aName pass:(NSString*) aPass; - (void) say:(NSString*) content; @end
FKUser.m
#import "FKUser.h" @implementation FKUser @synthesize name; @synthesize pass; - (id) initWithName:(NSString*) aName pass:(NSString*) aPass { if(self = [super init]) { name = aName; pass = aPass; } return self; } - (void) say:(NSString*) content { NSLog(@"%@说:%@",self.name , content); } // 会重写isEqual:方法,重写该方法的比较标准是, // 如果两个FKUser的name、pass相等,即可认为两个FKUser相等。 - (BOOL) isEqual:(id)other { if(self == other) { return YES; } if([other class] == FKUser.class) { FKUser* target = (FKUser*)other; return [self.name isEqualToString:target.name] && [self.pass isEqualToString:target.pass]; } return NO; } // 会重写isEqual:方法,重写该方法的比较标准是, // 如果两个FKUser的name、pass相等,即可认为两个FKUser相等。 - (NSUInteger) hash { NSUInteger nameHash = name == nil ? 0 : [name hash]; NSUInteger passHash = pass == nil ? 0 : [pass hash]; return nameHash * 31 + passHash; } // 重写description方法,可以直接看到FKUser对象的状态 - (NSString*) description { return [NSString stringWithFormat: @"<FKUser[name=%@, pass=%@]>" , self.name , self.pass]; } - (id)copyWithZone:(NSZone *)zone { NSLog(@"--正在复制--"); // 复制一个对象 FKUser* newUser = [[[self class] allocWithZone:zone] init]; // 将被复制对象的实变量的值赋给新对象的实例变量 newUser->name = name; newUser->pass = pass; return newUser; } @end
NSDictionary+print.h
#import <Foundation/Foundation.h> @interface NSDictionary (print) - (void) print; @end
NSDictionary+print.m
#import "NSDictionary+print.h" @implementation NSDictionary (print) - (void) print { NSMutableString* result = [NSMutableString stringWithString:@"{"]; // 使用快速枚举语法来遍历NSDictionary, // 循环计数器将依次等于该NSDictionary的每个key for(id key in self) { [result appendString:[key description]]; [result appendString:@"="]; // 使用下标访问法根据key来获取对应的value [result appendString: [self[key] description]]; [result appendString:@", "]; } // 获取字符串长度 NSUInteger len = [result length]; // 去掉字符串最后的两个字符 [result deleteCharactersInRange:NSMakeRange(len - 2, 2)]; [result appendString:@"}"]; NSLog(@"%@" , result); } @end
通过 key 来获取 value 有2种语法(2种方法功能相同):
dictionary objectForKey:key];(objectForKey方法)与
dictionary[key];(下标法)是等价的。推荐用后者(更简单易用)。
NSDictionaryTest.m
// Created by yeeku on 2013-4-22. // Copyright (c) 2013年 crazyit.org. All rights reserved. #import <Foundation/Foundation.h> #import "NSDictionary+print.h" #import "FKUser.h" int main(int argc , char * argv[]) { @autoreleasepool{ // 直接使用多个value,key的形式创建NSDictionary对象 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: [[FKUser alloc] initWithName:@"sun" pass:@"123"], @"one", [[FKUser alloc] initWithName:@"bai" pass:@"345"], @"two", [[FKUser alloc] initWithName:@"sun" pass:@"123"], @"three", [[FKUser alloc] initWithName:@"tang" pass:@"178"], @"four", [[FKUser alloc] initWithName:@"niu" pass:@"155"], @"five" , nil]; [dict print]; NSLog(@"dict包含%ld个key-value对", [dict count]); NSLog(@"dict的所有key为:%@" , [dict allKeys]); NSLog(@"<FKUser[name=sun,pass=123]>对应的所有key为:%@" , [dict allKeysForObject: [[FKUser alloc] initWithName:@"sun" pass:@"123"]]); // 获取遍历dict所有value的枚举器 NSEnumerator* en = [dict objectEnumerator]; NSObject* value; // 使用枚举器来遍历dict中所有value。 while(value = [en nextObject]) { NSLog(@"%@" , value); } // 使用指定代码块来迭代执行该集合中所有key-value对。 [dict enumerateKeysAndObjectsUsingBlock: // 该集合包含多个key-value对,下面代码块就执行多少次 ^(id key, id value, BOOL *stop) { NSLog(@"key的值为:%@" , key); [value say:@"疯狂iOS讲义"]; }]; } }
编译运行结果:
2015-10-04 11:54:25.892 923[1614:62069] {one=<FKUser[name=sun, pass=123]>, five=<FKUser[name=niu, pass=155]>, three=<FKUser[name=sun, pass=123]>, two=<FKUser[name=bai, pass=345]>, four=<FKUser[name=tang, pass=178]>} 2015-10-04 11:54:25.901 923[1614:62069] dict包含5个key-value对 2015-10-04 11:54:25.901 923[1614:62069] dict的所有key为:( one, five, three, two, four ) 2015-10-04 11:54:25.902 923[1614:62069] <FKUser[name=sun,pass=123]>对应的所有key为:( one, three ) 2015-10-04 11:54:25.903 923[1614:62069] <FKUser[name=sun, pass=123]> 2015-10-04 11:54:25.903 923[1614:62069] <FKUser[name=niu, pass=155]> 2015-10-04 11:54:25.904 923[1614:62069] <FKUser[name=sun, pass=123]> 2015-10-04 11:54:25.905 923[1614:62069] <FKUser[name=bai, pass=345]> 2015-10-04 11:54:25.905 923[1614:62069] <FKUser[name=tang, pass=178]> 2015-10-04 11:54:25.906 923[1614:62069] key的值为:one 2015-10-04 11:54:25.906 923[1614:62069] sun说:疯狂iOS讲义 2015-10-04 11:54:25.907 923[1614:62069] key的值为:five 2015-10-04 11:54:25.907 923[1614:62069] niu说:疯狂iOS讲义 2015-10-04 11:54:25.908 923[1614:62069] key的值为:three 2015-10-04 11:54:25.908 923[1614:62069] sun说:疯狂iOS讲义 2015-10-04 11:54:25.908 923[1614:62069] key的值为:two 2015-10-04 11:54:25.909 923[1614:62069] bai说:疯狂iOS讲义 2015-10-04 11:54:25.909 923[1614:62069] key的值为:four 2015-10-04 11:54:25.909 923[1614:62069] tang说:疯狂iOS讲义
对NSDictionary的key 排序
对NSDictionary的key 排序的方法如下(这些方法执行完成后将返回排序完成后的所有 key 组成的 NSArray):1.
keysSortedByValueUsingSelector:——根据NSDictionary的所有 value 的指定方法的返回值对 key 排序:调用 value 的该方法必须返回 NSOrderedAscending,NSOrderedDesending,NSOrderedSame三个值之一。
2.
keysSortedByValueUsingComparator:——使用指定的代码块来遍历键值 对,并根据执行结果(NSOrderedAscending,NSOrderedDesending,NSOrderedSame三个值之一)对NSDictionary的所有 key 进行排序。
3.
keysSortedByValueWithOptions:<#(NSSortOptions)#> usingComparator:——与上一种方法功能相似,可以传入一个额外的参数。
示例程序(用的是前面的类别文件):
#import <Foundation/Foundation.h> #import "NSDictionary+print.h" int main(int argc , char * argv[]) { @autoreleasepool{ // 直接使用多个value,key的形式创建NSDictionary对象 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: @"Objective-C" , @"one", @"Ruby" , @"two", @"Python" , @"three", @"Perl" , @"four", nil]; // 打印dict集合的所有元素 [dict print]; // 获取所有直接调用value的compare:方法对所有key进行排序。 // 返回排好序的所有key组成的NSArray。 NSArray* keyArr1 = [dict keysSortedByValueUsingSelector: @selector(compare:)]; NSLog(@"%@" , keyArr1); NSArray* keyArr2 = [dict keysSortedByValueUsingComparator: // 对NSDictionary的value进行比较,字符串越长,即可认为该value越大 ^(id value1, id value2) { // 下面定义比较大小的标准:字符串越长,即可认为value越大 if([value1 length] > [value2 length]) { return NSOrderedDescending; } if([value1 length] < [value2 length]) { return NSOrderedAscending; } return NSOrderedSame; }]; NSLog(@"%@" , keyArr2); // 将NSDictionary的内容输出到指定文件中 [dict writeToFile:@"mydict.txt" atomically:YES]; } }
编译运行结果:
2015-10-04 21:08:50.294 923[2781:170541] {one=Objective-C, three=Python, two=Ruby, four=Perl} 2015-10-04 21:08:50.296 923[2781:170541] ( one, four, three, two ) 2015-10-04 21:08:50.296 923[2781:170541] ( two, four, three, one )
对NSDictionary的key 进行过滤
NSDictionary提供了对所有 key 过滤的方法,这些方法执行完成 后返回满足 过滤条件的 key 组成的 NSSet。NSDictionary提供的过滤方法
NSDictionary提供了如下方法:1.
keysOfEntriesPassingTest:——使用代码块迭代处理 NSDictionary的每个键值对。对 键值对进行过滤,该代码块必须返回 BOOL 类型的值。——只有返回 YES 时,key才保留下来。
keysOfEntriesPassingTest:方法代码块参数说明。方法中的代码块可以接受3个参数:第一个参数代表,正在迭代处理的 key,第二个参数代表正在迭代处理的 value,第三个参数代表是否还需要继续 迭代。——如果第三个参数设置为 NO,该方法会立即停止迭代。
keysOfEntriesWithOptions:<#(NSEnumerationOptions)#> passingTest:——与上面的方法功能相似,可以额外传入 一个 NSEnumerationOptions 参数。
示例代码:
NSDictionaryFilter.m
#import <Foundation/Foundation.h> #import "NSDictionary+print.h" int main(int argc , char * argv[]) { @autoreleasepool{ // 直接使用多个value,key的形式创建NSDictionary对象 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:89] , @"Objective-C", [NSNumber numberWithInt:69] , @"Ruby", [NSNumber numberWithInt:75] , @"Python", [NSNumber numberWithInt:109] , @"Perl", nil]; // 打印dict集合的所有元素 [dict print]; // 对NSDictionary的所有key进行过滤 NSSet* keySet = [dict keysOfEntriesPassingTest: // 对NSDictionary的value进行比较,字符串越长,即可认为该value越大 ^(id key, id value, BOOL* stop) { // 当value的值大于80时返回YES // 这意味着只有value的值大于80的key才会被保存下来 return (BOOL)([value intValue] > 80); }]; NSLog(@"%@" , keySet); } }
编译运行结果:
2015-10-04 21:28:40.276 923[2860:178721] {Perl=109, Objective-C=89, Python=75, Ruby=69} 2015-10-04 21:28:40.280 923[2860:178721] {( Perl, "Objective-C" )}
使用自定义类作为NSDictionary的 key
如果程序打算使用自定义类作为NSDictionary的 key, 则该自定义类必须满足如下要求:- 该自定义类正确重写过
isEqual:和
hash方法。正确重写是指当2个对象通过
isEqual:判断相等时,,2个对象 的 Hash 方法返回值也相等。
- 该自定义 类必须实现了
copyWithZone:方法。该方法最好能返回对象的不可变副本。——这是出于安全性的考虑,防止 key 被 修改,破坏NSDictionary的完整性。每次添加,总会先调用 key 的 copy 方法复制该对象的不可变副本 ,以此副本作为 NSDictionary的 key。
在FKUser.m 文件中实现
copyWithZone:方法,并使该FKUser类 实现 NSCopying 协议(建议实现)。
- (id)copyWithZone:(NSZone *)zone { NSLog(@"--正在复制--"); // 复制一个对象 FKUser* newUser = [[[self class] allocWithZone:zone] init]; // 将被复制对象的实变量的值赋给新对象的实例变量 newUser->name = name; newUser->pass = pass; return newUser; } @end
test.m
#import <Foundation/Foundation.h> #import "NSDictionary+print.h" #import "FKUser.h" int main(int argc , char * argv[]) { @autoreleasepool{ FKUser* u1 = [[FKUser alloc] initWithName:@"bai" pass:@"345"]; // 直接使用多个value,key的形式创建NSDictionary对象 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: @"one", [[FKUser alloc] initWithName:@"sun" pass:@"123"], @"two", u1, @"three",[[FKUser alloc] initWithName:@"sun" pass:@"123"], @"four",[[FKUser alloc] initWithName:@"tang" pass:@"178"], @"five" ,[[FKUser alloc] initWithName:@"niu" pass:@"155"], nil]; // 将u1的密码设为nil u1.pass = nil; // 由于NSDictionary并未直接使用u1所指向的FKUser作为key, // 而是先复制了u1所指向对象的副本,然后以该副本作为key。 // 因此程序将可以看到dict的key不会受到任何影响。 [dict print]; } }
编译运行 结果;
2015-10-04 21:42:18.987 923[2923:184530] --正在复制-- 2015-10-04 21:42:18.991 923[2923:184530] --正在复制-- 2015-10-04 21:42:18.991 923[2923:184530] --正在复制-- 2015-10-04 21:42:18.991 923[2923:184530] --正在复制-- 2015-10-04 21:42:18.993 923[2923:184530] {<FKUser[name=bai, pass=345]>=two, <FKUser[name=sun, pass=123]>=one, <FKUser[name=tang, pass=178]>=four, <FKUser[name=niu, pass=155]>=five}s
NSMutableDictionary的功能与用法
创建NSMutableDictionary对象时,可以指定初始 容量。——因为,NSMutableDictionary可以动态添加键值对。1.
addEntriesFromDictionary:——将另一个字典中的键值对复制添加到当前字典中
2.
removeObjectForKey:——根据键删除键值对
3.
setObject:forKey:——设置一个键值对。
4.
setObject:forKeyedSubscript:——该 方法 使得程序可以通过下标法
5.
setDictionary——用另一个字典中所有的键值对替换当前字典中的键值对
6.
removeallObjects:——清空该字典。
7.
removeObjectsForKeys:——使用多个 key 组成的 NSArray 作为参数,同时删除多个 key 对应的键值对。
示例代码段 :
int main(int argc , char * argv[]) { @autoreleasepool{ // 直接使用多个value,key的形式创建NSDictionary对象 NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:89] , @"疯狂Android讲义", nil]; // 使用下标法设置key-value对。 // 由于NSDictionary中已存在该key, // 因此此处设置的value会覆盖前面的value。 dict[@"疯狂Android讲义"] = [NSNumber numberWithInt:99]; [dict print]; NSLog(@"--再次添加key-value对--"); dict[@"疯狂XML讲义"] = [NSNumber numberWithInt:69]; [dict print]; NSDictionary* dict2 = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:79] , @"疯狂Ajax讲义", [NSNumber numberWithInt:89] , @"Struts 2.x权威指南" , nil]; // 将另外一个NSDictionary中的key-value对添加到当前NSDictionary中 [dict addEntriesFromDictionary:dict2]; [dict print]; // 根据key来删除key-value对 [dict removeObjectForKey:@"Struts 2.x权威指南"]; [dict print]; } }
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 我是运营,我没有假期
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 如何成为一名专家级的开发人员
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- DB2数据库的安装
- C#实现把指定数据写入串口
- “传奇”图象数据存储方式
- 插件管理框架 for Delphi(一)
- 修复mysql数据库
- SQLServer 数据导入导出的几种方法小结
- MySQL数据备份之mysqldump的使用详解
- C#实现窗体间传递数据实例
- 使用CSS框架布局的缺点和优点小结
- 给你的数据库文件减肥
- Oracle数据更改后出错的解决方法