iOS macOS NSArray,NSMutableArray, NSDictionary, NSMutableDictionary,增加,删除,修改,查找取值,基本操作,数组中取数组
不可修改的数组对象 NSArray
创建方法:@[array]
初始化
//初始化 NSArray *array = [NSArray arrayWithObjects:@"A",@"B",@"C",@"D",@"E",@"F", nil]; NSArray *array1 = @[@"a",@"b",@"c",@"d"]; NSArray *array2 = [[NSArray alloc]init];//一般不会这样用,显得太傻 NSArray *array3 = @[];//一般要设置为空的数组也不会这样
一般NSArray就是赋值和读取而已,还有清空。
读取NSArray的值
//获取数组元素个数 NSLog(@"%lu",(unsigned long)array.count);//6 //获取数组最后一个元素 NSLog(@"%@",[array lastObject]);//F //获取数组第一个元素 NSLog(@"%@",[array firstObject]);//A //获取对象C在数组的位置 NSLog(@"%lu",(unsigned long)[array indexOfObject:@"C"]);// 2 //获取数组中索引为2的对象 NSLog(@"%@",[array objectAtIndex:2]);//C
遍历读取
//常规老方法 for (int i = 0 ; i< array.count; i++) { NSLog(@"遍历-%@",array[i]); } //增强循坏方法 for (NSString *str in array) { NSLog(@"遍历-%@",str); } //OC迭代器读取 [array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSLog(@"遍历-%@-%lu",obj,(unsigned long)idx); }];
NSArray中的所有对象执行方法(我还没搞懂这个啥有啥用)
@interface Student : NSObject - (void)log; - (void)logInfo:(NSString *)str; @end @implementation Student - (void)log{ NSLog(@"打印"); } - (void)logInfo:(NSString *)str{ NSLog(@"打印-%@",str); } @end --------------------- NSArray *array3 = @[[Student new],[Student new],[Student new],[Student new]]; [array3 makeObjectsPerformSelector:@selector(log)]; [array3 makeObjectsPerformSelector:@selector(logInfo:) withObject:@"p"];
NSArray排序(应该没什么大用)
NSArray *arr = @[@"90",@"20",@"30",@"10",@"50",]; //数组中的元素不可以是自定义的 NSArray *arr1 = [arr sortedArrayUsingSelector:@selector(compare:)]; NSLog(@"%@",arr1); /* 10,20,30,50,90 */ //NSSortStable:串行排序 NSSortConcurrent:并发排序 NSArray *arr2 = [arr sortedArrayWithOptions:NSSortStable usingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) { //每次调用 NSLog(@"ob1--%@,obj2--%@",obj1,obj2); return [obj1 intValue] < [obj2 intValue]; }]; NSLog(@"%@",arr2); /* 90,50,30,20,10 */
NSArray和NSString转换(这个很有用,非常有用!)
NSArray *arr = @[@"A",@"B",@"C",@"D"]; NSString *str = [arr componentsJoinedByString:@"-"]; NSLog(@"%@",str);//A-B-C-D NSString *str1 = @"A-B-C-D"; NSArray *arr1 = [str1 componentsSeparatedByString:@"-"]; NSLog(@"%@",arr1); /* A,B,C,D */
NSArray文件读写(这个还可以,少用)
NSArray *array = [NSArray arrayWithObjects:@"A",@"B",@"C",@"D",@"E",@"F", nil]; //将数组写入文件,本质是写入一个XML文件,iOS中一般写入plist,不能写入自定义对象 BOOL flag = [array writeToFile:@"/Users/soso/Desktop/demo1/NSArray/demo.plist" atomically:YES]; NSLog(@"%d",flag); //读文件 NSArray *arr = [NSArray arrayWithContentsOfFile:@"/Users/soso/Desktop/demo1/NSArray/demo.plist"]; NSLog(@"%@",arr);//A,B,C,D,E,F
NSArray清空数据(这个经常用!)
[NSArray removeAllObjects];
可修改的数组对象 NSMutableArray
创可变数组removeAllObjects引起崩溃
self.showDataSource =(NSMutableArray *)dataArray;
[self.showDataSource removeAllObjects];
解决方法:改成这样
self.showDataSource = [[NSMutableArray alloc] initWithArray:dataArray];
创建一个空的数组
NSMutableArray *array = [NSMutableArray alloc] init];//这并不是一个好方法
NSMutableArray *array = [NSMutableArray arrayWithCapacity:10]; //创建一个可变的数组长度为10
NSMutableArray *mutableArray = [NSMutableArray array];//AI给出的创建空数组元素方案
NSMutableArray *mutableArray = [NSMutableArray new];//新生代程序给出的方案
一、capacity概念
NSMutableArray *orderIds = [NSMutableArray arrayWithCapacity:self.dataArray.count]
初始化可变数组对象的长度,如果后面代码继续添加数组超过长度以后长度会自动扩充.
初始化方法 capacity后的NSUInteger代表了开辟内存的一个单位 初始在内存中开辟5个内存,如果之后数组元素多余5个,则会再开辟新的52个新的内存,[考虑到数组的连续内存的特性] 单位是以5,把之前的5个元素的内容拷贝到新的十个新的内存里面,把第六个 也放进去,然后释放初始状态创建的内存5个 最后得到了一块够用的连续的内存52
NSMutableArray *arr = [NSMutableArray array];
NSMutableArray *arr1 = [];
1.可变数组添加元素
arr = [NSMutableArray arrayWithArray:@[@"张三", @"李四", @"王五", @"崔六", @"1", @"2", @"3", @"4"]];
//添加元素 [arr addObject:@"A"]; NSLog(@"%@",arr);//A //插入一个元素 [arr insertObject:@"D" atIndex:2]; NSLog(@"%@",arr);// A,B,D,C //插入多个元素 NSRange range = NSMakeRange(2, 2); NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:range]; [arr insertObjects:@[@"H",@"G"] atIndexes:set]; NSLog(@"%@",arr);//A,B,H,G,D,C //将指定数组中的元素都取出来,放到arrM中,拼接数组 [arr addObjectsFromArray:@[@"B",@"C"]]; NSLog(@"%@",arr);// A,B,C
2.可变数组删除元素
//删除 [arr removeObject:@"B"];//删除其中一个元素 [arr removeObjectAtIndex:2];//删除指定位置的元素 [arr removeLastObject];//删除最后一个元素 [arr removeAllObjects];//清空数组
3.可变数组修改元素
//替换 [arr replaceObjectAtIndex:3 withObject:@"L"]; NSLog(@"%@",arr);//A,B,H,L,D,C
4.可变数组查找读取元素
//常规老方法 for (int i = 0 ; i< arr.count; i++) { NSLog(@"遍历-%@",array[i]); } //增强循坏方法 for (NSString *str in arr) { NSLog(@"遍历-%@",str); } //OC迭代器读取 [arr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSLog(@"遍历-%@-%lu",obj,(unsigned long)idx); }];
补充:⚠️⚠️⚠️
可变数组和不可变数组相互赋值
有两种情况
- 可变数组赋值给不可变数组
- 不可变数组赋值给可变数组
我回答的是
因为二者类型不匹配,在编译的时候编译器会报提示.面完验证了一下,发现理解还是有一点问题
把可变数组赋值给不可变的时候,没有报类型不匹配提示.(原因在于可变数组是不可变数组的子类,NSMutableArray继承自NSArray,多态的特性使得编译器不会提示)
把不可变数组赋值给可变数组的时候提示了类型冲突,验证我的观点.
从Log也可以看出,数组的实际类型取决于赋值等式的右边部分,因而虽然编译可以通过,运行时候回去查看变量的真实类型,如果混用了可变和不可变的方法,会导致方法找不到,导致crash.
比如给arrM2添加一个元素
-
[arrM2 addObject:@3];
运行代码,程序crash
arrM2在编译时候虽然被视作了可变数组,并且可以调用添加元素的方法,但是其实质仍旧是不可变的,故而在运行时检测到真实类型,会crash.
解决之道:
这是因为NSMutableArray和NSArray不是同一个类型造成的. 解决方法 // NSArray --> NSMutableArray NSMutableArray *myMutableArray = [myArray mutableCopy]; // NSMutableArray --> NSArray NSArray *myArray = [myMutableArray copy];
这里就近补充
// 将不可变字典转换为可变字典 NSMutableDictionary *mutableDict = [immutableDict mutableCopy]; // 将可变字典转换为不可变字典 NSDictionary *immutableDict = [mutableDict copy]; // 注意:即使转换成了不可变字典,也不能保证原始的可变字典不会被修改(除非你不再持有它的引用或确保它不会被其他地方修改)
⚠️⚠️⚠️数组中取数组
NSMutableArray *oldArray = [NSMutableArray arrayWithArray:@[@"000", @"111", @"222", @"333", @"444", @"555", @"666", @"777"]]; NSArray *newArray = [oldArray subarrayWithRange:NSMakeRange(2, 3)]; NSLog(@"AAA::%@",newArray);
再次补充
在数组中提取字段重新组成数组
//这是需要提取值的母数组 NSArray * dataArr = [dataDic objectForKey:@"day"]; //声明一个空的可变数组 NSMutableArray * muArr = [NSMutableArray array]; //或者 NSMutableArray * muArr = @[].mutableCopy; for(NSArray * dayArr in dataArr){ ResponseKlineData *unit = [[ResponseKlineData alloc] init]; unit.m_date = [[dayArr objectAtIndexCheck:0] intValue]; unit.m_open = [[dayArr objectAtIndexCheck:1] floatValue]; [klineDataArr addObject:unit]; } 或者 for(ResponseKlineData *unit in array){ [gethsDataArrZSJ addObject:[NSString stringWithFormat:@"%.3f", unit.floatValue]];//数组和字典里面只能装字符类型 } //得到新的小数组 muArr = klineDataArr ;//同类型 muArr = [klineDataArr copy];//不同类型
不可修改的字典对象 NSDictionary
创建方法: @{dictionary}
创建一个空的字典
//不要这样初始化,这是一个空的字典不可变字典一般直接赋值使用,常常用于一次性数据的读取,并且不可以做修改
NSDictionary *dict = [NSDictionary dictionary];//不可取
正确的使用
方法一:
NSDictionary *dict = [NSDictionary dictionaryWithObject:@"lnj" forKey:@"name"]; //根据key获取value NSString *name = [dict objectForKey:@"name"]; NSLog(@"name = %@", name);
方法二:
// 注意: key和value 是一一对应 NSDictionary *dict = [NSDictionary dictionaryWithObjects:@[@"lnj", @"30", @"1.75"] forKeys:@[@"name", @"age", @"height"]]; NSLog(@"%@ %@ %@", [dict objectForKey:@"name"], [dict objectForKey:@"age"], [dict objectForKey:@"height"]);
方法三:
//简写: NSDictionary *dict = @{key:value}; NSDictionary *dict = @{@"name": @"lnj"}; NSLog(@"%@", dict[@"name"]); NSDictionary *dict = @{@"name":@"lnj", @"age":@"30", @"height":@"1.75"}; NSLog(@"%@ %@ %@", dict[@"name"], dict[@"age"], dict[@"height"]);
只有读取赋值的信息,和删除字典
1.取值(遍历)
NSDictionary *dict = @{@"name":@"lnj", @"age":@"30", @"height":@"1.75"}; //获取字典中key和value的个数, 在字典中key称之为键, value称之为值 NSLog(@"count = %lu", [dict count]);
方法一:老式for循环写法
for (int i = 0; i < dict.count; ++i) { // 获取字典中所有的key NSArray *keys = [dict allKeys]; // 取出当前位置对应的key // NSLog(@"%@", keys[i]); NSString *key = keys[i]; NSString *value = dict[key]; NSLog(@"key = %@, value = %@", key, value); }
方法二:增强for循环写法
// 如何通过forin遍历字典, 会将所有的key赋值给前面的obj for (NSString *key in dict) { // NSLog(@"%@", key); NSString *value = dict[key]; NSLog(@"key = %@, value = %@", key, value); }
方法三:OC字典的迭代器来遍历
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { NSLog(@"key = %@, value = %@", key, obj); }];
清空NSDictionary字典
//需要确定你使用的字典是可变的 NSMutableDictionary *dictionary = [@{@"key":@"value"} mutableCopy]; NSLog(@"消空前:\n%@",dictionary); [dictionary removeAllObjects]; NSLog(@"消空后:\n%@",dictionary);
⚠️附加字典的文件操作
如何对字典文件进行读写?
1.将字典数据写入文件中
NSDictionary *dict = @{@"name":@"lnj", @"age":@"30", @"height":@"1.75"}; [dict writeToFile:@"/Users/xiaomage/Desktop/info.plist" atomically:YES];
2.从文件中读取字典数据
- 注意: 字典和数组不同, 字典中保存的数据是无序的
-
NSDictionary *newDict = [NSDictionary dictionaryWithContentsOfFile:@"/Users/xiaomage/Desktop/info.plist"]; NSLog(@"%@", newDict); NSArray *arr = @[@10, @20, @30, @5]; [arr writeToFile:@"/Users/xiaomage/Desktop/abc.plist" atomically:YES];
可修改的字典对象 NSMutableDictionary
NSMutableDictionary *dictM = [NSMutableDictionary dictionary];
1.增加元素
[dictM setObject:@"lnj" forKey:@"name"]; //简写: dictM[@"name"] = @"lnj";
2.删除元素
[dictM removeObjectForKey:@"name"]; [dictM removeObjectsForKeys:@[@"age", @"height"]];
3.修改元素
- 利用setObject方法给同名的key赋值, 那么新值会覆盖旧值
-
[dictM setObject:@"88" forKey:@"age"]; //简写: dictM[@"age"] = @"88";
4.查找取值读取
NSLog(@"name = %@", dictM[@"name"]);
注意⚠️
1.不能使用@{}来创建一个可变的字典
NSMutableDictionary *dictM = @{@"name":@"lnj"};//编译就会报错 [dictM setObject:@"30" forKey:@"age"];
2.
- 如果是不可变字典, 那么key不能相同
- 如果是不可变字典出现了同名的key, 那么后面的key对应的值不会被保存
- 如果是在可变数组中, 后面的会覆盖前面的
NSDictionary *dict = @{@"name":@"lmj", @"name":@"lnj"};
NSLog(@"dict = %@", dict);
NSMutableDictionary *dictM = [NSMutableDictionary dictionaryWithObjects:@[@"lmj", @"lnj"] forKeys:@[@"name", @"name"]];
NSLog(@"dict = %@", dictM);