OCfoudation框架(下)
前面学习了有关OCfoudation框架的部分内容,我们现在对于后面的内容继续学习。
文章目录
- OCfoudation框架(下)
- 数组(NSArray和NSMutableArray)
- 对集合元素整体调用方法
- 排序
- 使用枚举器遍历元素
- 快速枚举(for in)
- 可变数组
- 集合(NSSet 与 NSMutableSet)
- 功能与用法
- 判断元素重复的标准
- NSMutableSet的功能和用法
- NSCountedSet的用法
- 有序集合
- 字典
- 功能和用法
- 对key排序
- 对key进行过滤
- 用自定义类作为key
- NSmutableDictionary
数组(NSArray和NSMutableArray)
创建数组的常见方法介绍:
- arrary:创建一个不包含任何元素的空NSArray
- arrayWithContentsOfFile:/initWithContentsOfFile:读取文件内容来创建
- arrayWithObject:创建仅包含指定元素的NSArray
- arrayWithObjects:创建包含指定的N个元素的NSArray;
下面我们通过一段代码来运用这个数组的一些方法。
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array = [NSArray arrayWithObjects:@"iOS", @"Android", @"Java讲义", @"Html", @"structs", @"nanxun", nil];
NSLog(@"first: %@",[array objectAtIndex:0]);
NSLog(@"last:%@", [array lastObject]);
NSArray* arr1 = [array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 3)]];
NSLog(@"%@",arr1);
NSLog(@"Android:%ld", [array indexOfObject:@"Android"]);
NSLog(@"Android in (2,5): %ld", [array indexOfObject:@"Android" inRange:NSMakeRange(2, 3)]);
array = [array arrayByAddingObject:@"nannan"];
array = [array arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"krystal", @"zitai", nil]];
for (int i = 0; i < array.count; i++) {
NSLog(@"%@", [array objectAtIndex:i]);
}
NSArray* arr2 = [array subarrayWithRange:NSMakeRange(5, 3)];
[arr2 writeToFile:@"/Users/nanxun/Documents/testoc/foudation study/foudation study/myFile.txt" atomically:YES];
}
return 0;
}
打印结果如下:
接下来分析一下相关内容,先看我们在(2, 5)位置寻找Android的结果,发现他是一个数字9223372036854775807,这个数值实际上是NSNotFound这个常量的值,就下来我们通过两种方式在后面添加元素,arrayByAddingObject添加单个元素,arrayWithObjects方法是将一个数组中的元素全部追加到原数组后面。
同时可以看到,我门用程序直接输出数组的话,可知道中文无法正常输出,这个会转化成/U75af格式输出。
我们下面分析在NSArray中能否判断指定元素位于NSArray集合中的索引,我们的标准是什么?这个标准就是我们的isEqual: 方法,比较是否相同,为了理解这个部分的内容,我们建立一个FKUser来帮助自己理解相关内容。
接口部分
@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
实现部分
@implementation FKUser
- (id) initWithName:(NSString *)aName pass:(NSString *)aPass {
if (self = [super init]) {
self.name = aName;
self.pass = aPass;
}
return self;
}
- (void) say:(NSString *)content {
NSLog(@"%@说:%@", self.name, content);
}
- (BOOL) isEqual:(id)object {
if (self == object) {
return YES;
}
if ([object class] == [FKUser class]) {
FKUser* target = (FKUser*) object;
return [self.name isEqualToString:target.name] && [self.pass isEqualToString: target.pass];
}
return NO;
}
- (NSString*) description {
return [NSString stringWithFormat:@"FKUser[_name = %@, _pass = %@]", self.name, self.pass];
}
@end
主函数部分
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array = [NSArray arrayWithObjects:
[[FKUser alloc] initWithName:@"sun" pass:@"123"],
[[FKUser alloc] initWithName:@"bai" pass:@"345"],
[[FKUser alloc] initWithName:@"zhu" pass:@"654"],
[[FKUser alloc] initWithName:@"tang" pass:@"178"],
[[FKUser alloc] initWithName:@"niu" pass:@"155"], nil];
FKUser* newUser = [[FKUser alloc] initWithName:@"zhu" pass:@"654"];
NSUInteger pos = [array indexOfObject:newUser];
NSLog(@"newUser的位置为%ld", pos);
}
return 0;
}
输出结果为下:
这里我们发现了一个事情就是我们重新创建了一个对象,虽然该对象与集合中的任何对象都不相同,但是我们的程序还是可以返回该FKUser对象在该集合中的索引,这是因为他调用的是我们的isEqual方法
对集合元素整体调用方法
如果只是简单的调用集合元素的方法,主要有两种方法:
- makeObjectPerformSelector:依次调用NSArray集合中每个元素的指定方法需要传入一个SEL参数
- makeObjectsPerformSelcetor:withObject:一次调用集合中每个元素的指定方法,该方法第一个参数SEL用于指定调用那个方法,第二个参数用于调用集合元素方法时候传入参数;第三参数用来控制是否终止迭代,如果在处理某个元素后,将第三个元素复制为YES,该方法就终止迭代调用。
如果希望对集合中所有元素进行隐式遍历,并使用集合元素来执行某一段代码,可以使用以下三种方式
- enumerateObjectUsingBlock: 遍历集合中的所有元素,并依次使用元素来执行指定的代码块
- enumerateObjectsWithOptions:usingBolck: 和上面的差别就是可以传入一个号控制遍历的选项。
- enumerateObjectAtIndexes:options:usingBlock: 这个它增加了一个遍历指定范围内的元素,并一次使用元素来执行指定的代码块。
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array = [NSArray arrayWithObjects:
[[FKUser alloc] initWithName:@"sun" pass:@"123"],
[[FKUser alloc] initWithName:@"bai" pass:@"345"],
[[FKUser alloc] initWithName:@"zhu" pass:@"654"],
[[FKUser alloc] initWithName:@"tang" pass:@"178"],
[[FKUser alloc] initWithName:@"niu" pass:@"155"], nil];
[array makeObjectsPerformSelector:@selector(say:) withObject:@"下午好,NSArray真强大"];
NSString* content = @"疯狂iOS讲义";
[array enumerateObjectsAtIndexes: [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 2)]options:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"正在处理第%ld个元素,%@",idx, obj);
[obj say:content];
}];
}
return 0;
}
打印结果如下:
这两段代码,主要调用了两个函数,一个是调用了**makeObjectsPerformSelector:**方法通过withObjects为say方法传入参数.
第二个则是应用了enumerateObjectsAtIndexes:options:usingBlock:方法并用这些元素来这些指定的代码块,传入的代码块参数就代表程序对每个集合元素迭代执行的代码体。(笔者这里对与Block不了解,还需要后续学习进行补充)。
排序
对数组的排序函数主要有三种:
- sortedArrayUsingFunction:contes:该方法使用排序函数对集合元素进行一个排序,该排序函数必须返回NSOrderedDesceding,NSOrderedAscending,NSOrderedSame三个枚举常量。
- sortedArrayUsingSelector:该方法使用集合元素自身的方法对集合元素进行排序,它的排序函数同样会返回上面给出的三个枚举值。
- sortedArrayUsingComparator:该方法使用代码块对与集合元素进行排序
三种方法的返回值都是一个排好序的NSArray对象。
下面演示一下我们对于NSArray集合元素进行一个排序。
NSInteger inSort (id num1, id num2, void* context) {
int v1 = [num1 intValue];
int v2 = [num2 intValue];
if (v1 < v2) {
return NSOrderedAscending;
} else if (v1 == v2) {
return NSOrderedSame;
} else {
return NSOrderedDescending;
}
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array1 = [NSArray arrayWithObjects:@"C++",@"Python",@"Perl",@"C",@"Objective-C",@"Ruby", nil];
array1 = [array1 sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"%@", array1);
NSArray* array2 = [NSArray arrayWithObjects:[NSNumber numberWithInt:20], [NSNumber numberWithInt:12], [NSNumber numberWithInt:-8],[NSNumber numberWithInt:50], [NSNumber numberWithInt:19],nil];
array2 = [array2 sortedArrayUsingFunction:inSort context:nil];
NSLog(@"%@", array2);
NSArray* array3 = [array2 sortedArrayUsingComparator:^(id obj1, id obj2) {
if ([obj1 intValue] > [obj2 intValue]) {
return NSOrderedDescending;
} else if ([obj1 intValue] < [obj2 intValue]) {
return NSOrderedAscending;
} else {
return NSOrderedSame;
}
}];
NSLog(@"%@", array3);
}
return 0;
}
打印结果如下:
在上述代码中间我们示范了三种对于NSArrary进行排序的三种方法,第一种是调用NSString自身的compaer:方法进行排序(compare的比较和成语言中的strcmp()函数相似)。
后面是两种不同的方法,一个是调用代码块,一个是调用函数的方法。
使用枚举器遍历元素
我们有两个方法获得枚举器
- objectEnumerator:正序遍历
- reverseObjectEnumerator:逆序遍历
枚举器的方法有以下两个
- allObjects:获取枚举集合中所有的元素
- reverseObjectEnumerator:获取被枚举集合中的下一个元素。
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array1 = [NSArray arrayWithObjects:@"C++",@"Python",@"Perl",@"C",@"Objective-C",@"Ruby", nil];
NSEnumerator* en = [array1 objectEnumerator];
id object;
while (object = [en nextObject]) {
NSLog(@"%@", object);
}
NSLog(@"");
NSEnumerator* an = [array1 reverseObjectEnumerator];
while (object = [an nextObject]) {
NSLog(@"%@", object);
}
}
return 0;
}
打印结果为:
一种是升序,另一种是降序。
快速枚举(for in)
快速枚举的语法格式如下:
for(type variableName in collection) {
//variableName自动迭代访问每一个元素
}
tips:这里面如果用快速枚举来遍历NSDictionary对象的时候,它代表的是key值
下面给出一个示范
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array1 = [NSArray arrayWithObjects:@"C++",@"Python",@"Perl",@"C",@"Objective-C",@"Ruby", nil];
for (id object in array1) {
NSLog(@"%@", object);
}
}
return 0;
}
打印结果如下
可变数组
NSArray代表元素不可变的集合,一旦创建成功,程序不能向集合调价新的元素,这时候我们就要运用到我们的NSMutableArray.
它给出了增加(add),删除(remove),替换(replace)元素的方法。
NSMutableArray还提供了sortUsingSelector:、sortUsingComparator:、sortUsingFunction: context:方法,它们与前面介绍的NSArray的排序的方法类似,区别是NSArray的排序的方法返回的是一个新的NSArray对象,而NSMutableArray返回的是排序后的原来的对象。
下面给出代码示范
NSString *NSCollectionToString(NSArray *array) { // 将集合中的所有元素合成一个字符串便于我们打印
NSMutableString *result = [NSMutableString stringWithString:@"["];
for (id obj in array) {
[result appendString: [obj description]];
[result appendString:@","];
}
NSUInteger len = [result length];
[result deleteCharactersInRange:NSMakeRange(len - 1, 1)];//去掉最后一个字符
[result appendString:@"]"];
return result;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSMutableArray* array1 = [NSMutableArray arrayWithObjects:@"C++",@"Python",@"Perl",@"C",@"Objective-C",@"Ruby", nil];
[array1 addObject:@"Java"];
NSLog(@"%@", NSCollectionToString(array1));
[array1 addObjectsFromArray:[NSArray arrayWithObjects:@"Js", @"Ts", nil]];
NSLog(@"%@", NSCollectionToString(array1));
[array1 insertObject:@"Android" atIndex:2];
NSLog(@"%@", NSCollectionToString(array1));
[array1 insertObjects:[NSArray arrayWithObjects:@"web",@"server", nil] atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(3, 2)]];
NSLog(@"%@", NSCollectionToString(array1));
[array1 removeLastObject];
NSLog(@"%@", NSCollectionToString(array1));
[array1 removeObjectAtIndex:5];
NSLog(@"%@", NSCollectionToString(array1));
[array1 replaceObjectAtIndex:2 withObject:@"疯狂iOS"];
NSLog(@"%@", NSCollectionToString(array1));
}
return 0;
}
打印结果如下:
集合(NSSet 与 NSMutableSet)
NSSet集合不允许包含相同的元素(它没有明显的顺序),如果试图将两个相同的元素放在同一个NSSet集合中,则只会保留一个元素
功能与用法
实际上,NSArray与NSSet依然有大量的相似之处。
- 都可以通过count方法获取集合元素数量
- 可以用快速枚举遍历集合元素
- 可以通过objectEnumerator方法获取NSEnumerator枚举器对集合元素遍历。
- 提供了makeObjectsPerformSelector:方法对集合元素真题调用某个方法
接下来我们介绍一下NSSet的常用方法
- setByAddingObject:向集合中添加一个新元素,返回添加元素后的新集合
- setByAddingObjectsFromSet:使用NSSet集合向集合中添加多个新元素,返回新集合
- setByAddingObjectsFromArray:使用NSArray集合向集合中添加多个新元素,返回新集合
- allObjects:返回集合中所有元素组成的NSArray
- anyObject:返回集合中的某个元素。(但是并不保证随机返回集合元素)。
- containsObject:判断集合是否包含指定元素
- Member:判断该集合是否包括与该参数相等的元素,如果包含就返回相等的元素,反之则返回nil。
- objectsPassingTest:需要传入一个代码块对集合元素进行一个过滤,满足该代码块的集合元素会被保留下来并组成一个新的NSSet集合作为返回值
- objectsWithOptions:passingTest:和前一个方法的功能基本相似,只是可以额外地传入一个NSEnumerationOptions作为迭代参数
- isSubsetOfSet:判断是否为一个子集
- intersectsSet:判断是否有交集
- isEqualToset:判断集合是否相同
下面给出一段代码来理解相关内容
NSString *NSCollectionToString(id array) {
NSMutableString *result = [NSMutableString stringWithString:@"["];
for (id obj in array) {
[result appendString: [obj description]];
[result appendString:@","];
}
NSUInteger len = [result length];
[result deleteCharactersInRange:NSMakeRange(len - 1, 1)];//去掉最后一个字符
[result appendString:@"]"];
return result;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSSet* set1 = [NSSet setWithObjects:@"iOS", @"Andirod",@"web",@"server", nil];
NSLog(@"set个数为%ld", [set1 count]);
NSLog(@"%@", NSCollectionToString(set1));
NSSet* set2 = [NSSet setWithObjects:@"krystal",@"xiyang",@"fenfneko",@"web", nil];
NSLog(@"%@", NSCollectionToString(set2));
set1 = [set1 setByAddingObject:@"shenyi"];
NSSet* s1 = [set1 setByAddingObjectsFromSet:set2];
NSLog(@"并集合%@", NSCollectionToString(s1));
BOOL bo = [set2 isSubsetOfSet: set1];
NSLog(@"set2是否是set1子集集%ld",bo);
BOOL bb = [set1 containsObject:@"Andirod"];
NSLog(@"是否包含Andirod:%ld", bb);
NSLog(@"从set1中取出一个%@",[set1 anyObject]);
NSSet* fileteredSet = [set1 objectsPassingTest:^(id obj, BOOL *stop) {
return (BOOL)([obj length] > 3);
}];
NSLog(@"set1中元素长度大于8的集合元素有%@",NSCollectionToString(fileteredSet));
}
return 0;
}
下面是代码的结果:
这部分内容主要是一个演示相关代码的一个作用。
判断元素重复的标准
这里涉及到了一个Hash表的内容,我们每存入一个元素那么我们的NSSet会带调用该对象的一个Hash方法来计算一个Hash值,然后根据HashCode计算出元素在底层Hash表中的存储位置。如果出现了两个元素通过了isEqual方法但是它俩的值相同,那么我们这里的方式是通过链表将这两个元素连接起来。
这里我们就可以知道NSSet中判断两个元素是否相等的标准如下:
- 两个对象通过isEqual的方法返回YES
- 两个对象的hash方法的返回值也相等
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSSet* array = [NSSet setWithObjects:
[[FKUser alloc] initWithName:@"sun" pass:@"123"],
[[FKUser alloc] initWithName:@"bai" pass:@"345"],
[[FKUser alloc] initWithName:@"zhu" pass:@"123"],
[[FKUser alloc] initWithName:@"tang" pass:@"178"],
[[FKUser alloc] initWithName:@"niu" pass:@"155"], nil];
NSLog(@"元素个数为%ld", [array count]);
NSLog(@"%@", NSCollectionToString(array));
}
return 0;
}
这是我们之前用过的FKUser类别,我们在这个类别中间定义了我们的isEqual:方法它只要name和oass相同就说明了我们的两个对象是相同的。但是打印结果却不符合我们的一个预期
发现出现了两个相同的元素,因此我们要重写一下Hash方法。
- (NSUInteger) hash {
NSLog(@"===hash===");
NSUInteger nameHash = _name == nil ? 0 : [_name hash];
NSUInteger passHash = _pass == nil ? 0 : [_pass hash];
return nameHash * 31 + passHash;
}
修改之后发现结果就恢复正常了。
这里我们发现了我们执行了5次Hash方法,这一步说明我们每次添加一个集合与安素,总是会先调用该元素的Hash方法,在重写这两种方法的时候,我们的目的主要是为了满足NSSet的性质,为了保证哦我们的NSSet保持一个较高的性能。
tips:Hash方法对于NSSet是非常重要的,下面给出重写Hash方法的基本原则。
- 同一对象返回的Hash值应该是相同的
- isEqual:方法比较返回YES的时候,这两个对象的Hash应返回相等的值·
- 对象中所有被isEqual比较标准的实例变量都应该用来就算hashCode值。
一般情况我们的返回值都写成[f1 hash] * (质数) + [f2 hash]
。
NSMutableSet的功能和用法
和array相似,add(增加),remove(删除)。
主要要记住交,并,交,差集的函数
- unionSet:计算并集
- minusSet:计算差集
- intersectSet:计算交集
- setSet:用后一个元素替换已有集合中的所有元素
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSMutableSet* set1 = [NSMutableSet setWithCapacity:10];
[set1 addObject:@"Java"];
NSLog(@"add a one %@",NSCollectionToString(set1));
[set1 addObjectsFromArray:[NSArray arrayWithObjects:@"krystal",@"xiyang",@"zzr", nil]];
NSLog(@"add many %@", NSCollectionToString(set1));
[set1 removeObject:@"xiyang"];
NSLog(@"remove one %@",NSCollectionToString(set1));
NSMutableSet* set2 = [NSSet setWithObjects:@"fenfenko",@"shenyi", nil];
//[set1 unionSet: set2];
//[set1 minusSet: set2];
//[set1 intersectSet:set2];
[set1 setSet:set2];
NSLog(@"%@", NSCollectionToString(set1));
}
return 0;
}
打印结果如下:
NSCountedSet的用法
NSCountedSet主要是有一个特色就是它会为每一个元素增加一个该元素出现的个数,我们可以不可以添加元素,但是如果我们添加的元素重复了,但是会将该元素的添加次数加1.删除元素的时候也是将这个元素添加次数减1,知道它为0的时候,这个元素才会真正的从NSCountedSet中删除。
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSCountedSet* set1 = [NSCountedSet setWithObjects:@"iOS讲义",@"Android",@"Java", nil];
[set1 addObject:@"Java"];
[set1 addObject:@"Java"];
NSLog(@"%@", NSCollectionToString(set1));
NSLog(@"Java的添加次数为%ld", [set1 countForObject:@"Java"]);
[set1 removeObject:@"Java"];
NSLog(@"%@", NSCollectionToString(set1));
NSLog(@"Java的添加次数为%ld", [set1 countForObject:@"Java"]);
[set1 removeObject:@"Java"];
[set1 removeObject:@"Java"];
NSLog(@"%@", NSCollectionToString(set1));
NSLog(@"Java的添加次数为%ld", [set1 countForObject:@"Java"]);
}
return 0;
}
打印结果为:
这里就很好的体现了我们的NSCountedSet的特色。
有序集合
NSOrderedSet最主要的点在于可以保持与安素的添加顺序,而且每一个元素都有缩影,可以根据缩影来操作元素。
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSOrderedSet* set = [NSOrderedSet orderedSetWithObjects:[NSNumber numberWithInt:40],[NSNumber numberWithInt:12],[NSNumber numberWithInt:-9],[NSNumber numberWithInt:20], nil];
NSLog(@"first :%@", [set firstObject]);
NSLog(@"last:%@", [set lastObject]);
NSLog(@"索引为2的元素:%@", [set objectAtIndex:2]);
NSIndexSet* indexSet = [set indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL* stop) {
return (BOOL)([obj intValue] > 10); // 返回大于10的值
}];
NSLog(@"%@", indexSet);
}
return 0;
}
字典
这里的字典和C++中的map大致相同,它拥有一个键值对,所有key放在一个Set集合中,但是如果我们采用一个allKeys方法来返回却是一个NSArray。
功能和用法
初始化方法:一般以dictionary开头
访问方式:
@implementation NSDictionary (print)
- (void)print {
NSMutableString* result = [NSMutableString stringWithString:@"["];
for (id key in self) {
[result appendString:[key description]];
[result appendString:@"="];
[result appendString:[self[key] description]];
[result appendString:@", "];
}
NSUInteger len = [result length];
[result deleteCharactersInRange:NSMakeRange(len - 1, 1)];
[result appendString:@"]"];
NSLog(@"%@", result);
}
这段代码演示了两种经典的语法,通过key获取value值 self[key]
下面给出一段代码来演示相关内容。
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:[[FKUser alloc] initWithName:@"krystal" pass:@"24"], @"one", [[FKUser alloc] initWithName:@"xiyang" pass:@"33"], @"two",[[FKUser alloc] initWithName:@"flandre" pass:@"111"], @"three", [[FKUser alloc] initWithName:@"fenfenko" pass:@"2222"], @"four",[[FKUser alloc] initWithName:@"krystal" pass:@"24"], @"five", nil];
[dict print];
NSLog(@"有多少个key-value对:%ld", [dict count]);
NSLog(@"dict的所有key为%@", [dict allKeys]);
NSLog(@"krystal对应的所有key为%@", [dict allKeysForObject:[[FKUser alloc] initWithName:@"krystal" pass:@"24"]]);
NSEnumerator* en = [dict objectEnumerator];
NSObject* value;
while (value = [en nextObject]) {
NSLog(@"%@", value);
}
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) {
NSLog(@"key的值为:%@",key);
[value say:@"101牛逼"];
}];
}
return 0;
}
这里就演示了我们的dictionary的相关的代码演示。
对key排序
他和对于数组的排序一样,都是类似的,它的返回值同样是那三个关键字:NSOrderedAscending,NSOrderedDescending,NSOrderedSame。
接下来示范一下排序。
NSString *NSCollectionToString(id array) {
NSMutableString *result = [NSMutableString stringWithString:@"["];
for (id obj in array) {
[result appendString: [obj description]];
[result appendString:@","];
}
NSUInteger len = [result length];
[result deleteCharactersInRange:NSMakeRange(len - 1, 1)];//去掉最后一个字符
[result appendString:@"]"];
return result;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:@"iOS",@"one",@"Android",@"two",@"Java",@"three",@"Objective-c",@"four", nil];
[dict print];
NSArray* keyArr1 = [dict keysSortedByValueUsingSelector:@selector(compare:)];
NSLog(@"%@", keyArr1);
NSArray* keyArr2 = [dict keysSortedByValueUsingComparator:^(id value1, id value2) {
if ([value1 length] > [value2 length]) {
return NSOrderedDescending;
} else if ([value1 length] == [value2 length]) {
return NSOrderedSame;
} else {
return NSOrderedAscending;
}
}];
NSLog(@"%@", keyArr2);
}
return 0;
}
打印结果如下
对key进行过滤
- keysOfEntriesPassingTest:使用代码块迭代处理key-value对,只有符合代码块条件的会留下来。一共接收三个参数,第一个是正在迭代处理的key,第二个参数代表正在迭代处理的value,第三个参数代表是是否需要继续迭代,如果第三个参数设置成NO,这个方法就会立即停止迭代。
- keysOfEntriesWithOptions:passingTest:该方法的功能和前一个方法的功能基本相同,可以额外传入一个附加的NSEnumerationOptions的选项参数。
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:89], @"Objective-C",[NSNumber numberWithInt:69], @"Ruby",[NSNumber numberWithInt:75], @"Python",[NSNumber numberWithInt:109], @"Prel", nil];
[dict print];
NSSet* keySet = [dict keysOfEntriesPassingTest:^(id key, id value, BOOL* stop) {
return (BOOL)([value intValue] > 80);
}];
NSLog(@"%@", keySet);
}
return 0;
}
打印结果如下:
用自定义类作为key
我们可以用自己定义的类来作为key,但是要满足两个要求:
- 正确重写isEqual:方法和hash方法
- 自定义类实现了copyWithZone:方法,最好可以返回对象的不可变副
int main(int argc, const char * argv[]) {
@autoreleasepool {
FKUser* u1 = [[FKUser alloc] initWithName:@"krystal" pass:@"24"];
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
@"one", [[FKUser alloc] initWithName:@"xiyang" pass:@"23"],
@"two", [[FKUser alloc] initWithName:@"flandre" pass:@"22"],
@"three", [[FKUser alloc] initWithName:@"xiyang" pass:@"23"],
@"four", [[FKUser alloc] initWithName:@"fenfenko" pass:@"19"],
@"five", [[FKUser alloc] initWithName:@"niu" pass:@"155"],
@"six", u1, nil];
u1.pass = nil;
[dict print];
}
return 0;
}
打印结果如下:
这里我们可以看到它会让重复的key出现一次。
NSmutableDictionary
它其实也主要是提供了可以增加key-value对,和删除key-value对的一系列方法
代码演示
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"iOS", @"99", nil];
dict[@"99"] = @"iOSS";
[dict print];
dict[@"Android"] = @"ddd";
[dict print];
NSDictionary* dict2 = [NSDictionary dictionaryWithObjectsAndKeys:@"Java", @"sss", @"python", @"struct", nil];
[dict addEntriesFromDictionary:dict2];
[dict print];
[dict removeObjectForKey:@"sss"];
[dict print];
}
return 0;
}
打印结果如下: