目录
三、collection 类
1.NSSet / NSMutableSet
2.NSDictionary / NSMutableDictionary
3.NSArray / NSMutableArray
创建数组
遍历数组
NSMutableArray
数组排序
4.不可修改的类
5.过滤
6.collection 对象保存其他类型
Collection 类的实例用于保存指向其他对象的指针。除了 NSArray 及其子类 NSMutableArray 之外,还有 NSSet / NSMutableSet 和 NSDictionary / NSMutableDictionary。
NSSet 对象包含的内容是无序的,并且特定的对象只能出现一次。NSSet 对象最大的作用是检查某个对象是否存在,查询速度比遍历数组快得多(参照 C++ 底层可能也是红黑树?)。
与数组类似,NSSet 对象创建好后就不能对其中的指针进行添加或删除,NSMutableSet 可以。可以使用下面方法查询某个对象是否存在:当 NSSet 对象收到这个消息时,会在其包含的对象中查找和 x 相等的对象
-(BOOL) containObject:(id)x;
相等(equal):对象包含的值相等。相同(identical):指针指向同一个地址的内存。
NSDictionary 对象是一组 键-值对的集合,键通常是字符串,值可以是任意类型的对象,以键为索引:给出键就可以得到和键相连 值,键是独一无二的,键-值对是无序的。NSMutableDictionary 可以对其中的指针进行添加或删除。
方括号中提供键的名字,而不是正数索引。
用 collection 类也可以实现嵌套结构,例如以下 NSDictionary 实例的值为 NSArray 实例:
创建键值对使用 setObject:a forKey:b 方法
//创建一个 NSMutableDictionary 对象
NSMutableDictionary *friends = [NSMutableDictionary dictionary ];
//在键 bestFriend 后添加一个对象
[friends setObject:betty forKey:@"bestFriend"];
//使用新的对象 jane 代替 betty
[friends setObject:jane forKey:@"bestFriend"];
因为键是独一无二的,如果想要在现存的键后再添加第二个对象,第一个键值对就会被替换。
以下是加入了 NSMutableDictionary 管理 employee 的最新结构图:
与 NSString 相似,NSArray 也可以用字面常量语法创建实例。数组的内容写在方括号里,使用逗号分隔,前方带有@符号。
NSArray *dateList = @[now,tomorrow,yesterday];
NSArray 的实例是无法改变的,一旦 NSArray 实例被创建后,就无法添加或删除数组里的元素,也无法改变数组元素的顺序。
Objective-C 提供一种简化的 for 循环语法,称为快速枚举。省去了对数组计数的同时,高效地遍历数组的所有元素。
for(NSDate *d in dateList)
{
NSLog(@"Here is a date: %@.",d);
}
类似于 C++ 中的 auto 遍历语法。
可以添加、删除或对元素重新进行排序。(NSMutableArray 是 NSArray 的子类)
NSMutableArray *dateList =[NSMutableArray array]; //创建空数组
//将两个 NSDate 对象加入新创建的数组
[dateList addObject:now];
[dateList addObject:tomorrow];
//将 yesterday 指针插入数组的起始位置
[dateList addObject:yesterday atIndex:0];
//删除 yesterday 指针
[dateList removeObjectAtIndex:0];
//快速遍历
for(NSDate *d in dateList)
{
NSLog(@"Here is a date: %@.",d);
}
创建:上述程序使用了 array 类方法来创建 NSMutableArray,等同于 [[NSMutableArray alloc] init];
添加:addObject :元素 方法自动在尾部添加元素,如果要将对象添加到一个特定的索引上,则可以使用 insertObject:元素atIndex:下标。
删除:removeObjectAtIndex:下标 数组对象的计数也随之会减小。
遍历:不可在快速枚举过程中添加或者删除对象。
NSArray 因为不可修改,所以不可排序。对于 NSMutableArray 来说,使用排序的方法:
-(void)sortUsingDescriptors:(NSArray *)sortDescriptors;
//使用
[employees sortUsingDescriptors:@[voa,eid]];
sortDescriptor 排序描述对象包含两个信息:数组中的属性名;升序 ascending / 降序 decending。可以同时按优先级使用多个 sortDescriptor。
//假设现在要按姓氏的升序排列一个名单,则创建的 排序描述对象为
NSSortDescriptior *lastAsc = [NSSortDescriptior sortDescriptorWithKey:@"lastName" ascending:YES];
为什么要存在 NSArray、NSSet 和 NSDictionary 这样的不可修改的数组,主要是为了传输参数时的安全性,禁止获得数组的一方修改数组对象。实际的代码是,虽然对外声明的类型是 NSArray,但是实际创建的是 NSSMutableArray 对象,参考下面这个示例:
odds 方法所声明的返回类型是不可修改的 NSArray,调用方使用返回的 NSArray 实例增加或者删除对象时,虽然 odds 方法实际返回的是 NSMutableArray,编译器还是会发出警告。
程序中的其他代码可能在本线程正在使用这个可修改对象的时候修改它的内容,为了避免这种情况的发生,就需要复制一份私有的拷贝。NSMutableArray 的 copy 方法会制作一份自己的拷贝,并返回指向新数组对象的指针。
NSDate 和 NSNumber 只有不可修改的版本,如果要添加一个新的 NSDate 或 NSNumber 实例,就必须创建一个新的对象。
对 collection 进行过滤的时候,程序将对 collection 对象和一条逻辑语句进行比较,新合成一个满足这条语句的 collection 对象。
NSArray 有一个名为 filteredArrayUsingPredicate:的方法,可以创建一个新的数组,包含所有能够满足传入 NSPredicate 对象的对象。假设要回收物品总价值高于 70美元的员工的物品:
holder.valueOfAssets 表示调用 allAssets 数组中每个 asset 对象的 holder 所指向的 employee 的 valueOfAssets 方法;
NSPredicate 对象的条件语句可以支持非常复杂的格式。
类似的 NSSet 过滤方法为: filteredSetUsingPredicate
NSMutableSet 过滤方法为:filterUsingPredicate
set、array、dictionary 对象只能保存对象,如果要保存 float、int或指向结构的指针,则可以将其封装成对象,再存入 collection 对象。
NSValue 可以用来保存任意的数量值。
如果要将 nil 加入 collection,可以使用 NSNull类。[array addObject:[NSNull null] ];