Foundation Framework(2)
集合类
用来存储和管理一组对象的类
- 三种常用的集合类
NSArray:强调顺序,但是里面的元素可以相同
NSDictionary:键值对的形式,键不讲究顺序
NSSet:不强调顺序,元素是互不相同的
创建NSArray对象
方法一:
NSArray *array = [NSArray arrayWithObjects:@"str1", @"str2", @"str3", nil];
//调用了NSArray的工厂方法
//用nill标记序列的结束
方法二:
NSArray *array = [[NSArray alloc] initWithObjects:@"str1", @"str2", @"str3", nil];
方法三:
就像NSString创建字符串对象很常见一样,创建数组也太常用了,所以,OC为创建数组提供了一种简单的语法:
NSArray *array = @[@"str1", @"str2", @"str3"];
数组里的nil是结束标志,如果在中间出现nil,就会被认为这是末尾。但如果我们确实想在中间元素中有个空值,那这么办?
NSNull *null = [NSNull null];
//使用NSNull类(单例类)创建一个 null对象
//注意null 与nil的区别,null是有对象的,只是这个对象是空的,它只是用来占位的。而nil是真的没有一个对象。
注意:NSArray只能存储对象!
基本数据类型,比如C语言里的int,float,double, 结构体等,以及Foundation Framework里的NSInteger 都不能存储在NSArray里,因为它们都不是对象。
但如果确实想存储这些类型,怎么办?
Foundation Framework 提供了基本数据类型的包装对象。也就是说我们可以把这些基本数据类型包装在一个对象里面,这样就可以把这些数据作为对象来处理了。
包装类
- NSNumber
NSNumber 提供的把基本数据类型转换为对象的方法
NSNumber *intNum = [NSNumber numberWithInt:20];
NSNumber *doubleNum = [NSNumber numberWithDouble:20.5];
NSNumber *floatNum = [NSNumber numberWithFloat:98.98787f];
NSNumber *boolNum = [NSNumber numberWithBool:YES];
//使用NSNumber类方法,把基本数据类型当作参数传进去,这个方法就会返回一个NSNumber对象
如何把NSNumber对象里的数值取出来用?
int a = [intNum intValue];
double b = [doubleNum doubleValue];
float c = [floatNum floatValue];
BOOL d = [boolNum boolValue];
//每个对象都有特定的方法,可以返回特定类型的数据
每次要创建NSNumber对象的时候,都要调用NSNumber的类方法,很麻烦,有没有方便的办法?
ObjC2.0后,提供了更方便的字面量的写法。
NSNumber *intNum = @20;
NSNumber *doubleNum = @20.5;
NSNumber *floatNum = @98.98787f;
NSNumber *boolNum = @YES;
NSNumber可以对C语言的基本数据类型进行封装(成为对象),但是对于更复杂的,比如结构体,字节序列等,就得用另外一种方式进行封装,用NSNumber的父类,NSValue来处理。
- NSValue
如何把一个结构体包装进NSValue并生产一个NSValue对象?
typedef struct {
int a;
float b;
}DataType;
//这是个结构体,是无法包装进一个NSNumber里的
使用NSValue来包装结构体
DataType data;//定义一个结构体变量
NSValue *value = [NSValue valueWithBytes:&data objCType:@encode(Data Type)];
//调用NSValue的类方法,传入data的指针,
//第二个参数是data的数据类型(这个例子data的数据类型是结构体)
//如此这般便创建出一个NSValue对象
//注意`encode`是OC的关键字,可以得到数据类型的C的字符串表示。
//也就是说,`@encode(DataType)`返回的是`DataType`这么一个字符串
如何把包装在NSValue对象(Value)里的数据取出来?
[value getValue:&data];
//传入data变量的地址,getValue方法就会把包装起来的数据重新写回到我们传入的这个地址里,
//然后就可以直接使用里面的数据了。
现在我们有了NSNumber 和NSValue,我们就可以把各种数据类型写进NSArray数组里了。
读取NSArray某个下标位置的对象
- (id)objectAtIndex:(NSUInteger)index;
一个例子
NSArray *arrayOfString = @[@"str1", @"str2", @"str3", @"str4"];
NSString *str = [arrayOfString objectAtIndex:2];//返回第三个字符串的指针
//这个方法还是麻烦
更简洁的写法
NSString *str = arrayOfString[2];//跟C语言数组用法一样
另一个常用的集合类,NSDictionary
在字典里我们可以很方便的根据一个键来找到对应的数值。
对于字典的键,需要注意两点:
字典的键,必须是不可变对象
字典的键,必须两两不相同
- 如何创建一个字典
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
@64, @"intValue";
@19.8, @"doubleValue";
@YES, @"boolValue", nil];
//调用NSDictionary的一个工厂方法dictionaryWithObjectsAndKeys:
//注意先写值对象,再写键对象
//最后的nil也是用来判断传入参数序列的结束
- 字面量的创建方式
NSDictionary *dict = @{@"intValue":@64,
@"double":@19.8,
@"boolValue":@YES};
//键写在前面,后面是值
- 如何根据字典的键查找对应的值?
第一种方式
- (id)objectForKey:(id)aKey;
e.g.
NSObject *obj = [dict objectForKey:@"intValue"];
精简版
NSObject *obj = dict[@"intValue"];
//看着有点像数组的用法,只是数组下标变成了字典键
集合类NSSet
NSSet使用频率较低,当使用它是一般是考虑到效率问题。
当我们要判断一个集合里是不是有一个对象的时候,一个方法是使用NSArray数组扫一遍。而使用NSSet不需要遍历,效率高了很多。
- 如何创建一个NSSet对象?
NSSet *set = [NSSet setWithObjects:@"A", @"B", @"C", @"D", nil];
//跟NSArray类似,这也是运用类里的工厂方法来生成对象
- 如何判断一个集合里是否包含某个对象?
BOOL isContained = [set containsObject:@"A"];
//如果包含,则返回YES,否则返回NO.
因为NSSet使用频率不高,所以OC没提高更简便的方法