深入浅出Objective-C笔记(九)

Foundation Framework(2)


集合类

用来存储和管理一组对象的类

  • 三种常用的集合类

NSArray:强调顺序,但是里面的元素可以相同

NSDictionary:键值对的形式,键不讲究顺序

NSSet:不强调顺序,元素是互不相同的

深入浅出Objective-C笔记(九)_第1张图片
三种集合类的示意图.png
创建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没提高更简便的方法

你可能感兴趣的:(深入浅出Objective-C笔记(九))