类型编码
为了帮助运行时系统,编译器把每个方法的返回值和参数类型编码成一个字符串并且把字符串和方法选择器联系起来。它使用的编码方案在其他环境中也是有用的并且因此使用编译指令@encode()使得编码方案变得公开可用。当指定类型说明的时候,@encode() 返回一个字符串编码类型。这种类型可以是基本数据类型如int类型,指针类型,标记的结构体或联合体,或类名——任何类型,事实上,只要这种类型可以被用作C 语言中sizeof()操作符的参数。
char *buf1 = @encode(int **);
char *buf2 = @encode(struct key);
char *buf3 = @encode(Rectangle);
下表列出了类型编码。值得注意的是,当为了归档或者分发的目的编码一个对象的时候它们中的许多和你使用的编码部分相同。然而,这里列出了当写一个编码器的时候你不使用的编码,而且还列出了当写一个不能通过@encode()生成的编码器的时候你可能希望使用的编码。(参见Foundation框架索引中NSCoder类说明获取更多关于归档或者分发对象编码的信息)
表6-1 类型编码
编码 | 注释 |
---|---|
c | 字符 |
i | int |
s | short |
l | long 在64位程序中作为32位 |
q | long long |
C | 无符号字符 |
I | 无符号int |
S | 无符号short |
L | 无符号long |
Q | 无符号long long |
f | float |
d | double |
B | C++ bool or a C99 _Bool |
v | void |
* | 字符串(char *) |
@ | 对象(静态类型或者id类型) |
# | 类对象(Class) |
: | 方法选择器(SEL) |
[array type ] | 数组 |
{name=type... } | 结构体 |
(name =type... ) | 联合体 |
bnum | num位字段 |
^type | 类型指针 |
? | 未知类型(在其他方面,本编码是用于函数指针) |
重要:Objective-C不支持long double类型。@encode(longdouble)返回d,这是和用double相同的编码。
数组的类型编码被包含在一对方括号内;数组的元素个数立即被指定在前中括号之后数组类型之前。例如,一个有12个指向float类型的指针元素的数组被编码如下:
[12^f]
结构体被包含在一对大括号中,联合体被包含在一对圆括号中。结构体标签先被列出来,然后跟一个赋值符号并且结构体的字段代码按顺序列出来。例如,结构体:
typedef struct example {
id anObject;
char *aString;
int anInt;
} Example;
像这样被编码:
{example=@*i}
无论定义的类型名(Example)或者结构体标签(example)被传给@encode()编码的结果都是相同的。一个结构指针编码包含相同量的关于结构体字段的信息:
^{example=@*i}
然而,简洁移除内部的类型说明的另外的层次:
^^{example}
对象被当作结构体。例如,把NSObject类名传递给@encode()字段这个编码:
{NSObject=#}
NSObject类只声明一个实例变量,isa,类类型。
值得注意的是,@encode()指令不返回它们,当它们被在协议中用来声明方法的时候运行时系统使用在表6-2中列出来的另外的类型限定符编码。
表6-2 Objective-C方法编码
r | const |
n | int |
N | inout |
o | out |
O | bycopy |
R | byref |
V | oneway |