iOS类型编码Type Encodings与属性类型Property Type

关于runtime的文章中多次提到了类型编码,下边说说类型编码到底是什么鬼。

相关链接:

官方文档一
官方文档二
YYModel 源码历险记<二> 关于变量类型和编码
类型编码(Type Encodings)


类型编码(Type Encoding)
作为对Runtime的补充,编译器将每个方法的返回值和参数类型编码为一个字符串,并将其与方法的selector关联在一起。这种编码方案在其它情况下也是非常有用的,因此我们可以使用@encode编译器指令来获取它。当给定一个类型时,@encode返回这个类型的字符串编码。这些类型可以是诸如int、指针这样的基本类型,也可以是结构体、类等类型。事实上,任何可以作为sizeof()操作参数的类型都可以用于@encode()。

char *buf1 = @encode(int **);

char *buf2 = @encode(struct key);

char *buf3 = @encode(Rectangle);

下表列出了类型代码。注意,当编码一个对象用于归档或分配时,有许多代码时重叠的。然而,在编写编码器时,这里有些代码不能使用。也有些代码可以使用,但不是@encode()所产生的。(关于编码对象的归档和分配的更多信息,可见基础框架引用中NSCode类规范。)

   char *buf1 = @encode(int);
    char *buf2 = @encode(char);
    char *buf3 = @encode(long double);
    char *buf4 = @encode(void);
    char *buf5 = @encode(Class);
    char *buf6 = @encode(id);
    char *buf7 = @encode(char *);
    char *buf8 = @encode(NSArray *);

输出为:
这里写图片描述

重要:Objective-C 不支持long double 类型。@encode(long double) 返回d,和double编码一样。
数组类型代码是包含在方括号中,在开括号后,数组类型前指定数组中元素的个数。例如,

float a[] = {1.0, 2.0, 3.0};
NSLog(@"array encoding type: %s", @encode(typeof(a)));
输出: array encoding type: [3f] 

结构在括号中指定,在圆括号中结合。最先列出结构标记,然后是等号和序列中列出的结构的范围代码

typedef struct example {  
    id   anObject;  
    char *aString;  
    int  anInt;  
} Example; 

结构编码如下:

{example=@*i}  

对象被当做结构。例如,传递NSObject类名到@encode() 产生如下编码:

{NSObject=#}  

NSObject类声明一个实例变量,isa,作为类型类。
注意:尽管@encode()指令不返回它们,在协议中用来声明方法时,运行时系统使用表6-2中列出的额外编码列表来限定类型。这里写图片描述

属性类型Property Type

苹果对每一个变量的类型进行了编码,对方法的类型也进行了编码,于是我们获取到变量的attributes时,就是经过编译器编码后得到的属性。
我们来写个方法打印下看看到底是什么鬼?


+ (NSArray *)properties1{
    NSArray *propertiesArray = [NSMutableArray array];
    // 1.获得所有的属性
    unsigned int outCount = 0;
    objc_property_t *properties = class_copyPropertyList(self, &outCount);

    for (int i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        NSLog(@"name:%s---attributes:%s",((propertyStruct)property)->name,((propertyStruct)property)->attributes);

        //事实上苹果已经给出了我们获取属性attributes的方法
//        property_getAttributes(property);
//        property_getName(property);

    }

    return propertiesArray;
}

objc_property_t *properties的原型大概就是这个样子:

typedef struct property_t {
    const char *name;
    const char *attributes;
} *propertyStruct;

所以我们可以用这个方法去获取到属性的名字和描述。打印结果如下:

2016-09-01 17:38:29.726 RuntimeDemo[45809:23195325] name:name---attributes:T@"NSString",C,N,V_name
2016-09-01 17:38:29.726 RuntimeDemo[45809:23195325] name:age---attributes:Ti,N,V_age
2016-09-01 17:38:29.726 RuntimeDemo[45809:23195325] name:father---attributes:T@"NSString",C,N,V_father
2016-09-01 17:38:29.727 RuntimeDemo[45809:23195325] name:secondModel---attributes:T@"DDSecondModel",&,N,V_secondModel
2016-09-01 17:38:29.727 RuntimeDemo[45809:23195325] name:thirdModel---attributes:T@"NSArray",&,N,V_thirdModel

NSLog打印的结果可能有点不一样,其实原型是这样的:

"T@\"NSArray\",&,N,V_thirdModel"

中间会多一个@\,这牵扯到c与oc的转换,在OC字符串中 \” -> “,\是转义的意思,不占用字符

我们试着来看懂一个编码的类型,首先这个T@”NSArray”指的这个变量是NSArray类型,&代表的是retain的在ARC状态下也就是strong类型,N表示的是是nonatomic的,V_thirdModel代表这个变量名是thirdModel,再来看看我们的声明,好像是并不是那么难懂,再来查一查官方文档,对这些字符进行了定义:

官方文档又给出了一些例子:
这里写图片描述

enum FooManChu { FOO, MAN, CHU };

struct YorkshireTeaStruct { int pot; char lady; };

typedef struct YorkshireTeaStruct YorkshireTeaStructType;

union MoneyUnion { float alone; double down; };

这里写图片描述
文章开头给出了官方文档地址,可以再去看看。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值