美文网首页
深入浅出Objective-C笔记(九)

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

作者: 无聊的呆子 | 来源:发表于2015-11-21 22:17 被阅读24次

    Foundation Framework(2)


    集合类

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

    • 三种常用的集合类

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

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

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

    三种集合类的示意图.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笔记(九)

          本文链接:https://www.haomeiwen.com/subject/qwnlhttx.html