前言
本周学习了OC中Foundation框架的剩余内容,下面总结一下本周的学习成果
一、数组(NSArray与NSMutableArray)
NSArray是前文OC集合概述中提到的三大集合体系之一,它代表元素有序、可重复的集合并且集合中的每个元素都有对应索引。跟C语言一样,我们也可以通过索引来访问集合的元素。
1.1.NSArray的功能和用法
我们可以通过类方法和实例方法创建NSArray并且传入的参数类似,通过类方法创建以array开头,通过实例方法创建以init开头。
下面是几种常见的创建方法:
array:创建一个不包含任何元素的空Array
arrayWithContentsOfFile:/initWithContentsOfFile:读取文件内容来创建NSArray
arrayWithObject:/initWithObject:创建只包含指定元素的NSArray
arrayWithObjects:/initWtihObjects:创建包含N个元素的NSArray
使用简化语法:@[元素1, 元素2, … ]
下面介绍几个NSArray的几个常用方法
1.查询集合元素在NSArray中的索引
2.根据索引值取出NSArray集合中的元素
3.对集合元素整体调用方法
4.对NSArray集合进行排序
5.取出NSArray集合中的部分集合组成新集合
示例代码如下:
NSArrayTest.m
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array = [NSArray arrayWithObjects:@"刻晴", @"甘雨", @"雷神", @"草神", @"妮露", nil];
NSLog(@"第一个元素:%@", [array objectAtIndex:0]);
NSLog(@"索引为1的元素:%@", [array objectAtIndex:1]);
NSLog(@"最后一个元素:%@", [array lastObject]);
//获取从索引为2的元素开始,以及后面三个元素组成的新集合
NSArray* arr1 = [array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 3)]];
NSLog(@"%@", arr1);
//获取元素在集合中的位置
NSLog(@"甘雨在集合中的位置是:%ld", [array indexOfObject:@"甘雨"]);
//获取元素在集合指定范围中的位置
NSLog(@"在1~4范围中甘雨的位置是:%ld", [array indexOfObject:@"甘雨" inRange:NSMakeRange(1, 3)]);
//向数组的最后追加元素
//原NSArray本身并没有改变,只是将新返回的NSArray赋给array
array = [array arrayByAddingObject:@"钟离"];
//向array数组的最后追加另一个数组的所有元素
//原NSArray本身并没有改变,只是将新返回的NSArray赋给array
array = [array arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"原神", @"星穹铁道", nil]];
for (int i = 0; i < array.count; i++) {
NSLog(@"%@", [array objectAtIndex:i]);
}
//获取array数组中索引为5~7处的所有元素
NSArray* arr2 = [array subarrayWithRange:NSMakeRange(4, 2)];
//将NSArray集合的元素写入文件
[arr2 writeToFile:@"myFile.txt" atomically:YES];
NSArray* arr3 = [NSArray arrayWithContentsOfFile:@"myFile.txt"];
NSLog(@"%@", arr3);
}
return 0;
}
运行结果如下:
需要注意的是遍历NSArray集合时可以用[array objectAtIndex:i]也可以用array[i]来访问元素。
如果要查找的元素不在指定范围内的话程序会返回9223372036854775807这是NSNotFound的值。
使用arrayByAddingObject:或arrayWithObjects:方法向NSArray集合后面追加元素后会返回一个新的NSArray对象而原来的NSArray并不会改变。
通过上面的结果我们可以看出当程序直接输出集合的元素时如果时中文则会转为\U75af格式的Unicode形式而通过索引访问进行输出的话则会直接输出中文
NSArray判断集合是否包含指定元素是通过将集合中的某个元素与被查找元素使用isEqual:方法比较。
下面先通过一段代码来感受一下
示例代码如下:
User.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface User : NSObject
@property(nonatomic, copy)NSString* name;
@property(nonatomic, copy)NSString* pass;
- (id)initWithName:(NSString*)aname pass:(NSString*)apass;
@end
NS_ASSUME_NONNULL_END
User.m
#import "User.h"
@implementation User
- (id)initWithName:(NSString *)aname pass:(NSString *)apass {
if (self = [super init]) {
self.name = aname;
self.pass = apass;
}
return self;
}
//重写isEqual方法,判断标准是name和pass相等则认为它们相等
- (BOOL)isEqual:(id)object {
if (self == object) {
return YES;
}
if ([object class] == User.class) {
User* target = (User*)object;
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];
}
@end
main.m
#import <Foundation/Foundation.h>
#import "User.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array = @[[[User alloc] initWithName:@"张三" pass:@"123"], [[User alloc] initWithName:@"丁真" pass:@"12345"], [[User alloc] initWithName:@"蔡徐坤" pass:@"114514"], [[User alloc] initWithName:@"李四" pass:@"666"]];
//查找指定新User对象在集合中的索引
User* newuser = [[User alloc] initWithName:@"丁真" pass:@"12345"];
NSUInteger pos = [array indexOfObject: newuser];
NSLog(@"newuser的位置为:%ld", pos);
}
return 0;
}
运行结果如下:
新创建的对象与集合中的对象都不相同但是依然能返回在集合中的索引这是因为该对象与集合中索引为1的对象的name和pass属性一样。
1.2.对集合元素整体调用方法
如果要对集合中的所有元素或部分元素整体调用方法可以通过下面两种方法:
makeObjectPerformSelector: 依次调用NSArray集合中每个元素的指定方法,该方法需要传入一个SEL参数来指定调用方法。
makeObjectsPerformSelector:withObject: 依次调用NSArray集合中每个元素的指定方法,该方法需要传入一个SEL参数来指定调用方法,再传入一个用于调用集合元素的方法时传入参数。
如果对集合中的元素进行隐式遍历并使用元素来执行代码块可通过如下方法来实现:
示例代码如下:
User.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface User : NSObject
@property(nonatomic, copy)NSString* name;
@property(nonatomic, copy)NSString* pass;
- (id)initWithName:(NSString*)aname pass:(NSString*)apass;
- (void)say:(NSString*)message;
@end
NS_ASSUME_NONNULL_END
User.m
#import "User.h"
@implementation User
- (id)initWithName:(NSString *)aname pass:(NSString *)apass {
if (self = [super init]) {
self.name = aname;
self.pass = apass;
}
return self;
}
- (void)say:(NSString *)message {
NSLog(@"%@说:%@", self.name, message);
}
@end
main.m
#import <Foundation/Foundation.h>
#import "User.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//使用简化语法创建NSArray对象
NSArray* array = @[[[User alloc] initWithName:@"张三" pass:@"123"], [[User alloc] initWithName:@"丁真" pass:@"12345"], [[User alloc] initWithName:@"蔡徐坤" pass:@"114514"], [[User alloc] initWithName:@"李四" pass:@"666"]];
//对集合整体调用方法
[array makeObjectsPerformSelector:@selector(say:) withObject:@"原神最好玩了"];
NSString* content = @"星穹铁道";
//迭代集合内指定范围内的元素并使用该元素来执行代码块
[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;
}
运行结果如下:
1.3.对NSArray进行排序
下面列举几个常见的排序方法:
1.sortedArrayUsingFunction:context: 这个方法是使用排序函数对集合元素进行排序
2.sortedArrayUsingSelector: 这个方法使用集合元素自身的方法进行排序
3.sortedArrayUsingComparator: 这个方法使用代码块对集合元素进行排序以上三个方法都必须返回NSOrderedDescending、NSOrderedAscending、NSOrderedSame这三个枚举值并且都会返回一个排序好的新的NSArray对象也就是说原来的NSArray对象不会改变。
示例代码如下:
NSArraySort.m
#import <Foundation/Foundation.h>
//定义比较函数,根据两个对象的intValue进行比较
NSComparisonResult intSort(id num1, id num2, void* context) {
int v1 = [num1 intValue];
int v2 = [num2 intValue];
if (v1 < v2)
return NSOrderedAscending;
if (v1 > v2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
//初始化一个元素为NSNmuber的NSArray对象
NSArray* array1 = @[@"希尔", @"卡芙卡", @"三月七", @"姬子", @"布洛妮娅",@"符玄"];
//使用集合的compare:方法进行排序
array1 = [array1 sortedArrayUsingSelector: @selector(compare:)];
NSLog(@"%@ %@ %@ %@ %@ %@", array1[0], array1[1], array1[2], array1[3], array1[4], array1[5]);
//初始化一个元素为NSNumber的NSArray对象
NSArray* array2 = @[[NSNumber numberWithInt:20], [NSNumber numberWithInt:12], [NSNumber numberWithInt:-8], [NSNumber numberWithInt:50], [NSNumber numberWithInt:19]];
//使用intSort函数进行排序
array2 = [array2 sortedArrayUsingFunction:intSort context:nil];
NSLog(@"%@", array2);
//使用代码块对集合元素进行排序
NSArray* array3 = [array2 sortedArrayUsingComparator: ^(id obj1, id obj2) {
//该代码块就是根据集合元素的intValue进行比较
if ([obj1 intValue] > [obj2 intValue]) {
return NSOrderedDescending;
}
if ([obj1 intValue] < [obj2 intValue]) {
return NSOrderedAscending;
}
else {
return NSOrderedSame;
}
}];
NSLog(@"%@", array3);
}
return 0;
}
运行结果如下:
第一种方法是使用NSString自身的compare:方法进行排序,其比较大小的方法是通过字符对应的编码进行。
第二种方法是调用外部函数进行排序。
第三种方法是调用代码块进行排序。
1.4.使用枚举器遍历NSArray集合元素
如果使用枚举器来遍历NSArray集合元素的话可以通过以下两种方法来返回枚举器:
1.objectEnumerator: 该方法返回一个顺序枚举器
2.reverseObjectEnumerator: 该方法返回一个逆序枚举器
上述方法只是返回枚举器如果要遍历元素还要通过枚举器来调用下面两种方法:
1.allObject:该方法获取枚举集合中所有元素
2.nextObject:该方法获取枚举集合中的下一个元素
示例代码如下:
NSEnumeratorTest.m
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array1 = @[@"刻晴", @"甘雨", @"雷电将军", @"妮露"];
[array1 writeToFile:@"myFile.txt" atomically:YES];
//读取前面写入的磁盘文件,用文件内容来初始化NSArray集合
NSArray* array = [NSArray arrayWithContentsOfFile:@"myFile.txt"];
//获取NSArray的顺序枚举器
NSEnumerator* en = [array objectEnumerator];
id object;
NSLog(@"-----下面顺序遍历-----");
while (object = [en nextObject]) {
NSLog(@"%@", object);
}
NSLog(@"-----下面逆序遍历-----");
//获取NSArray的逆序枚举器
en = [array reverseObjectEnumerator];
while (object = [en nextObject]) {
NSLog(@"%@", object);
}
}
return 0;
}
运行结果如下:
1.5.快速枚举
快速枚举遍历元素无需获得集合长度,也不需要使用索引依次访问每个元素,其语法格式如下:
for (type variableName in collection) {
//variableName自动迭代每个元素
}
type是集合元素的类型, variableName是一个形参名
示例代码如下:
ForInTest.m
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array1 = @[@"刻晴", @"甘雨", @"妮露", @"雷电将军"];
[array1 writeToFile:@"myFile.txt" atomically:YES];
//读取前面写入的磁盘文件,用文件内容来初始化NSArray集合
NSArray* array = [NSArray arrayWithContentsOfFile:@"myFile.txt"];
for (id object in array) {
NSLog(@"%@", object);
}
}
return 0;
}
运行结果如下:
快速枚举的本质是一个for-each循环,它不需要循环条件和迭代语句。
1.6.可变数组(NSMutableArray)
与NSArray不同的是NSMutableArray可以对数组本身进行添加、删除和替换集合元素。
其主要方法如下:
示例代码如下:
NSMutableArrayTest.m
#import <Foundation/Foundation.h>
//定义一个函数,该函数用于把NSArray集合转换为字符串
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 - 2, 2)];
[result appendString:@"]"];
return result;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array1 = @[@"刻晴", @"甘雨", @"纳西妲", @"影"];
[array1 writeToFile:@"myFile.txt" atomically:YES];
//读取前面写入的磁盘文件,用文件内容来初始化NSArray集合
NSMutableArray* array = [NSMutableArray arrayWithContentsOfFile:@"myFile.txt"];
//向集合最后添加元素
[array addObject:@"妮露"];
NSLog(@"添加最后一个元素后:%@", NSCollectionToString(array));
//使用NSArray向集合尾部添加多个元素
[array addObjectsFromArray:[NSArray arrayWithObjects:@"芭芭拉", @"宵宫", nil]];
NSLog(@"添加最后两个元素后:%@", NSCollectionToString(array));
//向集合指定位置插入元素
[array insertObject:@"胡桃" atIndex:2];
NSLog(@"在索引为2处插入一个元素后:%@", NSCollectionToString(array));
//使用NSArray向指定位置插入多个元素
[array insertObjects:[NSArray arrayWithObjects:@"申鹤", @"绫华", nil] atIndexes: [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(3, 2)]];
NSLog(@"插入多个元素后:%@", NSCollectionToString(array));
//删除集合最后一个元素
[array removeLastObject];
NSLog(@"删除最后一个元素后:%@", NSCollectionToString(array));
//删除集合中指定索引的元素
[array removeObjectAtIndex:5];
NSLog(@"删除索引为5元素后:%@", NSCollectionToString(array));
//删除索引为2~4处的元素
[array removeObjectsInRange:NSMakeRange(2, 3)];
NSLog(@"删除索引为2~4的多个元素后:%@", NSCollectionToString(array));
//替换索引为2的元素
[array replaceObjectAtIndex:2 withObject:@"钟离"];
NSLog(@"替换索引为2的元素后:%@", NSCollectionToString(array));
}
return 0;
}
运行结果如下:
二、集合
集合中的元素各不相同并且没有明显的顺序
2.1.NSSet的功能和用法
使用NSSet添加的元素没有顺序也就没有索引来支持访问集合中的元素但是它在以下几个方面和NSArray有相似之处。
初始化NSSet集合也有类方法和实例方法两种方法,类方法以set开头,实例方法以init开头,下面是几种常见的方法:
1.setByAddingObject:给集合添加元素
2.setByAddingObjectsFromSet:给集合中添加多个元素
3.allObjects:返回该集合中所有元素组成的NSArray
4.anyObject:返回集合中随机的某个元素
5.containsObject:判断集合是否包含该元素
6.member:判断该集合是否包含与该参数相等的元素,如果包含则返回相等的元素否则返回nil;
7.objectsPassingTest:需传入一个代码块对集合进行过滤,满足条件的被保留最后返回一个新的NSSet集合
8.objectsWithOptions:passingTest:与上面功能类似只是多传入了一个NSEnumerationOptions迭代选项参数
9.isSubSetOfSet:判断当前集合是否是另一个集合的子集
10.intersectsSet:判断两个集合是否有交集
11.isEqualToSet:判断两个集合的元素是否相等
示例代码如下:
#import <Foundation/Foundation.h>
//一个将set集合转换为字符串的函数
NSString *NSCollectionToString(id collection) {
NSMutableString *result = [NSMutableString stringWithString:@"["];
for (id obj in collection) {
[result appendString:[obj description]];//默认打印输出为<类名:内存地址>
[result appendString:@", "];
}
NSUInteger len = [result length];//获取字符串长度
//去除字符串的最后两个字符
[result deleteCharactersInRange:NSMakeRange(len - 2, 2)];
[result appendString:@"]"];
return result;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
//用四个元素初始化set集合
//然后我们故意传入两个相等的元素,集合只会保留一个元素
NSSet *set1 = [NSSet setWithObjects:@"刻晴", @"甘雨", @"雷电将军", @"妮露", nil];
//然后输出我们集合中元素的个数
NSLog(@"set1集合中的元素个数为%ld", [set1 count]);
NSLog(@"%@", NSCollectionToString(set1));
NSSet *set2 = [NSSet setWithObjects:@"胡桃", @"申鹤", @"纳西妲", nil];
NSLog(@"%@", NSCollectionToString(set2));
//向集合set1中添加单个元素,并将添加元素后生成的集合赋给set1
[set1 setByAddingObject:@"八重神子"];
NSLog(@"%@", NSCollectionToString(set1));
//然后我们添加多个元素
NSSet *s = [set1 setByAddingObjectsFromSet:set2];
NSLog(@"%@", NSCollectionToString(s));//计算两个集合的并集
BOOL b = [set1 intersectsSet:set2];//判断两个集合是否有相同元素
BOOL bo = [set2 isSubsetOfSet:set1];//判断set2是否为set1的子集
BOOL bb = [set1 containsObject:@"甘雨"];//判断是否包含指定元素
NSLog(@"%d", b);
NSLog(@"%d", bo);
NSLog(@"%d", bb);
NSLog(@"set1中随机取出一个元素:%@", [set1 anyObject]);
NSLog(@"set1中随机取出一个元素;%@", [set1 anyObject]);
}
return 0;
}
运行结果如下:
2.2.NSSet判断集合元素重复的标准
当向NSSet存入元素时,NSSet会调用该对象的hash方法来获取hashcode值并根据该值来决定在底层hash表中的存储位置,如果不相同则会存到不同的位置。如果相同接着用isEqual方法判断,如果返回NO则认为不相同,则存在底层Hash表的同一位置并形成链式结构,如果返回YES则添加元素失败。
为FKUser类重写hash方法,其代码如下:
/重写hash方法,比较标准是如果两个User的name、pass相等,那么两个User的hash方法返回值相等
- (NSUInteger) hash {
NSUInteger nameHash = self.name == nil ? 0: [self.name hash];
NSUInteger passHash = self.pass == nil ? 0: [self.pass hash];
return nameHash * 31 + passHash;
}
重写hash方法的基本规则如下:
1.程序运行过程中,同一个对象多次调用Hash应该返回相同的值。
2.当两个对象通过isEqual:方法比较返回YES时,这两个对象的Hash应返回相等的值。
3.对象中作为isEqual:比较标准的成员变量,都应该用来计算hashCode值。
2.3.NSMutableSet的功能和用法
与NSMutableArray和NSArray的关系类似,NSMUtableSet也是在NSSet的基础上添加了添加和删除元素的方法,并且还添加了计算交集、并集、补集的方法。
三、字典(NSDictionary与NSMutableDictonary)
NSDictonary用于保存具有映射关系的数据,因此NSDictonary集合保存两组值,一组值用来保存NSDictionary的key,一组值用来保存NSDictionary里的value。key和value可以是任何指针类型的数据,NSDictonary的key不允许重复。
3.1.NSDictioanry的功能和用法
创建NSDictionary也可以通过类方法和实例方法来创建,类方法以dictionary开头,实例方法以init开头。下面是几类常见的方法:
创建好了NSDictionary对象,接下来就可以通过方法来访问集合中所包含的key或value。下面是几种常见的方法:
示例代码如下:
NSDictionary+print.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSDictionary (print)
- (void)print;
@end
NS_ASSUME_NONNULL_END
NSDictonary+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
User.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface User : NSObject
@property(nonatomic, copy)NSString* name;
@property(nonatomic, copy)NSString* pass;
- (id)initWithName:(NSString*)aname pass:(NSString*)apass;
- (void)say:(NSString*)message;
@end
NS_ASSUME_NONNULL_END
User.m
#import "User.h"
@implementation User
- (id)initWithName:(NSString *)aname pass:(NSString *)apass {
if (self = [super init]) {
self.name = aname;
self.pass = apass;
}
return self;
}
//重写isEqual方法,判断标准是name和pass相等则认为它们相等
- (BOOL)isEqual:(id)object {
if (self == object) {
return YES;
}
if ([object class] == User.class) {
User* target = (User*)object;
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];
}
- (void)say:(NSString *)message {
NSLog(@"%@说:%@", self.name, message);
}
@end
main.m
#import <Foundation/Foundation.h>
#import "NSDictionary+print.h"
#import "User.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//直接使用多个value-key对的形式创建NSDictionary对象
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:[[User alloc] initWithName:@"刻晴" pass:@"123"], @"one", [[User alloc] initWithName:@"甘雨" pass:@"345"], @"two", [[User alloc] initWithName:@"刻晴" pass:@"123"], @"three", [[User alloc] initWithName:@"妮露" pass:@"178"], @"four", [[User alloc] initWithName:@"雷电将军" pass:@"155"], @"five", nil];
[dict print];
NSLog(@"dict包含%ld个key-value对", [dict count]);
NSLog(@"dict的所有key为:%@", [dict allKeys]);
NSLog(@"<User[name = 刻晴, pass = 123>对应的所有key为:%@", [dict allKeysForObject:[[User alloc] initWithName:@"刻晴" pass:@"123"]]);
//获取遍历dict所有的value的枚举器
NSEnumerator* en = [dict objectEnumerator];
id 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: @" 原神最好玩了"];
}
];
}
return 0;
}
运行结果如下:
3.2.对NSDictionary进行排序
NSDictionary提供方法对NSDictionary的所有key进行排序,执行完这些方法后将返回排序好的所有key组成的NSArray。其提供的方法如下:
示例代码如下:
NSDictionary+print.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSDictionary (print)
- (void)print;
@end
NS_ASSUME_NONNULL_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
main.m
#import <Foundation/Foundation.h>
#import "NSDictionary+print.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//使用简化语法创建NSDictionary对象
NSDictionary* dict = @{@"one": @"刻晴", @"two": @"甘雨", @"three": @"雷电将军", @"four": @"申鹤"};
//打印dict集合的所有元素
[dict print];
//获取所有直接调用value的compare:方法对所有的key进行排序
//返回排序好的所有key组成的NSArray
NSArray* keyArr1 = [dict keysSortedByValueUsingSelector:@selector(compare:)];
NSLog(@"%@", keyArr1);
NSArray* keyArr2 = [dict keysSortedByValueUsingComparator: ^(id value1, id value2) {
//下面定义比较大小的标准,字符串越长,认为value越大
if ([value1 length] > [value2 length]) {
return NSOrderedDescending;
}
if ([value1 length] < [value2 length]) {
return NSOrderedAscending;
}
else {
return NSOrderedSame;
}
}];
NSLog(@"%@", keyArr2);
//将NSDictonary的内容输出到指定文件中
[dict writeToFile:@"mydict.txt" atomically:YES];
//读取文件
NSDictionary* dict1 = [[NSDictionary alloc] initWithContentsOfFile:@"mydict.txt"];
NSLog(@"%@", dict1);
}
return 0;
}
运行结果如下:
3.3.对NSDictionary的key进行过滤
NSDictionary提供方法对NSDictionary的所有key进行过滤,执行完这些方法后将返回满足条件的key组成的NSSet,其方法如下:
示例代码如下:
NSDictionaryFilter.m
#import <Foundation/Foundation.h>
#import "NSDictionary+print.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//使用简化语法创建NSDictionary对象
NSDictionary* dict = @{@"刻晴": [NSNumber numberWithInt:89], @"甘雨": [NSNumber numberWithInt:69], @"雷电将军": [NSNumber numberWithInt:75], @"妮露": [NSNumber numberWithInt:109]};
//打印dict集合的所有元素
[dict print];
//对NSDictionary的所有key进行过滤
NSSet* keySet = [dict keysOfEntriesPassingTest: ^(id key, id value, BOOL* stop) {
//当value的值大于80时返回Yes
//这意味着只有value的值大于80的key才会被保存下来
return (BOOL)([value intValue] >80);
}];
NSLog(@"%@", keySet);
}
return 0;
}
运行结果如下:
3.4.使用自定义类作为NSDictionary的key
如果想使用自定义类作为NSDictionary的key,则自定义类需满足如下要求:
1.该自定义类正确重写过isEqual:和hash方法。也就是说当两个对象通过isEqual:方法判断相等时,两个对象的hash方法返回值也相等。
2.该自定义类必须实现copyWithZone:方法,该方法最好返回该对象的不可修改副本。
示例代码如下:
User.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface User : NSObject<NSCopying>
@property(nonatomic, copy)NSString* name;
@property(nonatomic, copy)NSString* pass;
- (id)initWithName:(NSString*)aname pass:(NSString*)apass;
- (id)copyWithZone:(NSZone *)zone;
@end
NS_ASSUME_NONNULL_END
User.m
#import "User.h"
@implementation User
- (id)initWithName:(NSString *)aname pass:(NSString *)apass {
if (self = [super init]) {
self.name = aname;
self.pass = apass;
}
return self;
}
//重写isEqual方法,判断标准是name和pass相等则认为它们相等
- (BOOL)isEqual:(id)object {
if (self == object) {
return YES;
}
if ([object class] == User.class) {
User* target = (User*)object;
return [self.name isEqualToString:target.name] && [self.pass isEqualToString:target.pass];
}
return NO;
}
//重写hash方法,比较标准是如果两个User的name、pass相等,那么两个User的hash方法返回值相等
- (NSUInteger) hash {
NSUInteger nameHash = self.name == nil ? 0: [self.name hash];
NSUInteger passHash = self.pass == nil ? 0: [self.pass hash];
return nameHash * 31 + passHash;
}
//重写description方法,可以直接看到User对象的状态
- (NSString*)description {
return [NSString stringWithFormat:@"<User[name = %@, pass = %@]>", self.name, self.pass];
}
//重写copyWtihZone方法
- (id)copyWithZone:(NSZone *)zone {
NSLog(@"===正在复制===");
//复制一个对象
User* newUser = [[[self class] allocWithZone:zone] init];
//将复制对象的实例变量赋给新对象的实例变量
newUser.name = _name;
newUser.pass = _pass;
return newUser;
}
@end
mian.m
#import <Foundation/Foundation.h>
#import "NSDictionary+print.h"
#import "User.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
User* u1 = [[User alloc] initWithName:@"刻晴" pass:@"345"];
//使用简化语法创建NSDictionary对象
NSDictionary* dict = @{[[User alloc] initWithName:@"甘雨" pass:@"123"]: @"one", u1: @"two", [[User alloc] initWithName:@"甘雨" pass:@"123"]: @"three",[[User alloc] initWithName:@"雷电将军" pass:@"178"]: @"four", [[User alloc] initWithName:@"妮露" pass:@"155"]: @"five"};
//将u1的密码设为nil
u1.pass = nil;
[dict print];
}
return 0;
}
运行结果如下:
3.5.NSMutableDictionary的功能和用法
类似于NSMutableArray与NSArray的关系,NSMutableDictioanry在NSDictionary的基础上增添了添加key-value对、删除key、value对的方法。
其主要新增的方法如下:
示例代码如下:
main.m
#import <Foundation/Foundation.h>
#import "NSDictionary+print.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//使用单个key-value对来创建NSMutableDictionary对象
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:89], @"刻晴", nil];
//使用下标法设置key-value对。由于NSDictionary中已存在该key所以此处设置的value会覆盖前面的value
dict[@"刻晴"] = [NSNumber numberWithInt:99];
[dict print];
NSLog(@"再次添加key-value对");
dict[@"雷电将军"] = [NSNumber numberWithInt:69];
[dict print];
NSDictionary* dict2 = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:79], @"甘雨", [NSNumber numberWithInt:79], @"妮露", nil];
//将另一个NSDictionary对象中的key-value对添加到当前NSDictionary中
[dict addEntriesFromDictionary:dict2];
[dict print];
//根据key删除key-value对
[dict removeObjectForKey:@"妮露"];
[dict print];
}
return 0;
}
运行结果如下:
总结
以上就是本篇文章的所有内容,如果对你有帮助的话请点赞支持一下~