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

来源:互联网 发布:vincizhang淘宝上有吗 编辑:程序博客网 时间:2024/05/16 14:29

关于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_name2016-09-01 17:38:29.726 RuntimeDemo[45809:23195325] name:age---attributes:Ti,N,V_age2016-09-01 17:38:29.726 RuntimeDemo[45809:23195325] name:father---attributes:T@"NSString",C,N,V_father2016-09-01 17:38:29.727 RuntimeDemo[45809:23195325] name:secondModel---attributes:T@"DDSecondModel",&,N,V_secondModel2016-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