@encode
,@
编译器指令 之一,返回一个给定类型编码为一种内部表示的字符串(例如,@encode(int)
→ i
),类似于 ANSI C 的 typeof
操作。苹果的 Objective-C 运行时库内部利用类型编码帮助加快消息分发。
Objective-C type encodings
编码 | 意义 |
---|---|
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) |
当然,用图表很不错,但是用代码实践更好:
NSLog(@"int : %s", @encode(int));
NSLog(@"float : %s", @encode(float));
NSLog(@"float * : %s", @encode(float*));
NSLog(@"char : %s", @encode(char));
NSLog(@"char * : %s", @encode(char *));
NSLog(@"BOOL : %s", @encode(BOOL));
NSLog(@"void : %s", @encode(void));
NSLog(@"void * : %s", @encode(void *));
NSLog(@"NSObject * : %s", @encode(NSObject *));
NSLog(@"NSObject : %s", @encode(NSObject));
NSLog(@"[NSObject] : %s", @encode(typeof([NSObject class])));
NSLog(@"NSError ** : %s", @encode(typeof(NSError **)));
int intArray[5] = {1, 2, 3, 4, 5};
NSLog(@"int[] : %s", @encode(typeof(intArray)));
float floatArray[3] = {0.1f, 0.2f, 0.3f};
NSLog(@"float[] : %s", @encode(typeof(floatArray)));
typedef struct _struct {
short a;
long long b;
unsigned long long c;
} Struct;
NSLog(@"struct : %s", @encode(typeof(Struct)));
结果:
类型 | 编码 |
---|---|
int |
i |
float |
f |
float * |
^f |
char |
c |
char * |
* |
BOOL |
c |
void |
v |
void * |
^v |
NSObject * |
@ |
NSObject |
# |
[NSObject] |
{NSObject=#} |
NSError ** |
^@ |
int[] |
[5i] |
float[] |
[3f] |
struct |
{_struct=sqQ} |
这里有一些特别需要注意的:
- 指针的标准编码是加一个前置的
^
,而char *
拥有自己的编码*
。这在概念上是很好理解的,因为 C 的字符串被认为是一个实体,而不是指针。 -
BOOL
是c
,而不是某些人以为的i
。原因是char
比int
小,且在 80 年代 Objective-C 最开始设计的时候,每一个 bit 位都比今天的要值钱(就像美元一样)。BOOL
更确切地说是signed char
(即使设置了-funsigned-char
参数),以在不同编译器之间保持一致,因为char
可以是signed
或者unsigned
。 - 直接传入
NSObject
将产生#
。但是传入[NSObject class]
产生一个名为NSObject
只有一个类字段的结构体。很明显,那就是isa
字段,所有的NSObject
实例都用它来表示自己的类型。
方法编码
如苹果的 “Objective-C Runtime Programming Guide” 中所提到的,有一大把内部使用的类型编码无法用 @encode()
返回。
以下是协议中声明的方法的类型修饰符:
Objective-C Method Encodings
编码 | 意义 |
---|---|
r | const |
n | in |
N | inout |
o | out |
O | bycopy |
R | byref |
V | oneway |
对于那些熟悉 NSDistantObject 的人,你无疑会认出这些是 Distributed Objects 的残留。
参考:
https://nshipster.cn/type-encodings/
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100
网友评论