为了帮助运行时系统,编译器将每个方法的返回值类型和参数类型编码成了字符串,并把字符串与方法选择器关联起来。 它使用的编码方案在其他情况下也是有用的,因此该方案使用 @encode() 编译器指令设置成了公共可用的。当给定一个类型说明, @encode() 会返回这个类型的字符串编码。这个类型可以是基础类型如 int,指针,带标签的结构或联合,或者类名——实际上是可以用作C语言 sizeof() 运算符的参数的任何类型。
char *buf1 = @encode(int **);
char *buf2 = @encode(struct key);
char *buf3 = @encode(Rectangle);
下表列出了类型编码。注意他们中许多与你为了归档或分发而编码一个对象时使用的代码重叠了。并且,有的代码你不能在撰写编码器时使用,而有的代码你想要用于撰写编码器时不会由 @encode() 产生。(关于编码对象以归档或分发的更多信息,参见Foundation框架参考中的 NSCoder 类说明。)
Table 6-1 Objective-C type encodings
Code | Meaning |
---|---|
c | A char |
i | An int |
s | A short |
l | A long l is treated as a 32-bit quantity on 64-bit programs. |
q | A long long |
C | An unsigned char |
I | An unsigned int |
S | An unsigned short |
L | An unsigned long |
Q | An unsigned long long |
f | A float |
d | A double |
B | A C++ bool or a C99 _Bool |
v | A void |
* | A character string (char *) |
@ | An object (whether statically typed or typed id) |
# | A class object (Class) |
: | A method selector (SEL) |
[array type] | An array |
{name=type…} | A structure |
(name=type…) | A union |
bnum | A bit field of num bits |
^type | A pointer to type |
? | An unknown type (among other things, this code is used for function pointers) |
重要: Objective-C 不支持 long double 类型。@encode(long double) 返回 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,类型是Class。
注意尽管 @encode() 不直接返回它们,运行时系统还为类型修饰词使用了额外的编码,列在表6-2中,它们用于在协议中声明方法。
Table 6-2 Objective-C method encodings
Code | Meaning |
---|---|
r | const |
n | in |
N | inout |
o | out |
O | bycopy |
R | byref |
V | oneway |