先测试下Objective-C的方法通过编译变成了什么?
@interface Person : NSObject
@property (nonatomic, strong) NSString* name;
@property (nonatomic, assign) NSInteger age;
- (void)test;
@end
@implementation Person
- (void)test {
NSLog(@"%s",__func__);
}
+ (void)test {
NSLog(@"%s",__func__);
}
@end
通过
clang -arch x86_64 -rewrite-objc main.m -o main.cpp
获取到cpp 文件,发现里面有
static struct /*_method_list_t*/ {
unsigned int entsize; // sizeof(struct _objc_method)
unsigned int method_count;
struct _objc_method method_list[1];
} _OBJC_$_CATEGORY_CLASS_METHODS_NSObject_$_YYExtension __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_objc_method),
1,
{{(struct objc_selector *)"test", "v16@0:8", (void *)_C_NSObject_YYExtension_test}}
};
其中这个**"v16@0:8"是什么呢?就是SEL Type Encodings**
- (void)test { }
v -> void 返回值是void
16 -> 总共占用字节数
@ -> OC 对象,就是id self
0 -> self offset 是 0
: -> SEL ,就是SEL cmd
8 -> cmd 的 offset 是 8
To assist the runtime system, the compiler encodes the return and argument types for each method in a character string and associates the string with the method selector. The coding scheme it uses is also useful in other contexts and so is made publicly available with the @encode() compiler directive. When given a type specification, @encode() returns a string encoding that type. The type can be a basic type such as an int, a pointer, a tagged structure or union, or a class name—any type, in fact, that can be used as an argument to the C sizeof() operator.
为了帮助运行时系统,编译器将每个方法的返回和参数类型编码为字符串,并将该字符串与方法选择器关联。它使用的编码方案在其他上下文中也很有用,因此可以通过@encode()编译器指令公开使用。给定类型说明后,@ encode()返回编码该类型的字符串。该类型可以是基本类型,例如int,指针,带标签的结构或联合,或类名-实际上可以用作C sizeof()运算符的参数的任何类型。
char *buf1 = @encode(int **);
char *buf2 = @encode(struct key);
char *buf3 = @encode(Rectangle);
NSLog(@"buf1->%s buf2->%s buf3->%s",buf1, buf2, buf3);
// buf1->^^i buf2->{key=if} buf3->{Rectangle=#}
Code | Meaning |
---|---|
s | A short |
l | A long |
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) |
NSString *format = @"\t";
NSLog(@"@encode(char)%@ %s", format, @encode(char));
NSLog(@"@encode(int)%@ %s", format, @encode(int));
NSLog(@"@encode(long)%@ %s", format, @encode(long));
NSLog(@"@encode(long long)%@ %s", format, @encode(long long));
NSLog(@"@encode(unsigned char)%@ %s", format, @encode(unsigned char));
NSLog(@"@encode(unsigned int)%@ %s", format, @encode(unsigned int));
NSLog(@"@encode(unsigned short)%@ %s", format, @encode(unsigned short));
NSLog(@"@encode(unsigned long)%@ %s", format, @encode(unsigned long));
NSLog(@"@encode(unsigned long long)%@ %s", format, @encode(unsigned long long));
NSLog(@"@encode(float)%@ %s", format, @encode(float));
NSLog(@"@encode(float *)%@ %s", format, @encode(float *));
NSLog(@"@encode(double)%@ %s", format, @encode(double));
NSLog(@"@encode(double *)%@ %s", format, @encode(double *));
NSLog(@"@encode(BOOL)%@ %s", format, @encode(BOOL));
NSLog(@"@encode(void)%@ %s", format, @encode(void));
NSLog(@"@encode(void *)%@ %s", format, @encode(void *));
NSLog(@"@encode(char *)%@ %s", format, @encode(char *));
NSLog(@"@encode(NSObject)%@ %s", format, @encode(NSObject));
NSLog(@"@encode(NSObject *)%@ %s", format, @encode(NSObject *));
NSLog(@"@encode([NSObject class])%@ %s", format, @encode(typeof([NSObject class])));
NSLog(@"@encode(SEL)%@ %s", format, @encode(typeof(@selector(viewDidLoad))));
int intArray[3] = { 0, 0, 0 };
NSLog(@"@encode(intArray)%@ %s", format, @encode(typeof(intArray)));
float floatArray[3] = { 0.1f, 0.2f, 0.3f };
NSLog(@"@encode(floatArray)%@ %s", format, @encode(typeof(floatArray)));
typedef struct _struct {
short a;
long long b;
unsigned long long c;
double *d;
} Struct;
NSLog(@"@encode(Struct)%@ %s", format, @encode(typeof(Struct)));
NSLog(@"@encode(NSError)%@ %s", format, @encode(NSError));
NSLog(@"@encode(NSError ** )%@ %s", format, @encode(typeof(NSError **)));
输出
@encode(char) c
@encode(int) i
@encode(long) q
@encode(long long) q
@encode(unsigned char) C
@encode(unsigned int) I
@encode(unsigned short) S
@encode(unsigned long) Q
@encode(unsigned long long) Q
@encode(float) f
@encode(float *) ^f
@encode(double) d
@encode(double *) ^d
@encode(BOOL) B
@encode(void) v
@encode(void *) ^v
@encode(char *) *
@encode(NSObject) {NSObject=#}
@encode(NSObject *) @
@encode([NSObject class) #
@encode(SEL) :
@encode(intArray) [3i @encode(floatArray) [3f @encode(Struct) {_struct=sqQ^d} @encode(NSError) {NSError=#^vq@@} @encode(NSError ** ) ^@