先看一下消息轉發流程: 在forwardInvocation這一步,你必須要實現一個方法: 該方法用於說明消息的返回值和參數類型。NSMethodSignature是方法簽名,它是用來記錄返回值和參數類型的一個對象。看一下與該類相關的方法: 2和3兩個方法是根據SEL來構造NSMethodSigna ...
先看一下消息轉發流程:
在forwardInvocation這一步,你必須要實現一個方法:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("");
該方法用於說明消息的返回值和參數類型。NSMethodSignature是方法簽名,它是用來記錄返回值和參數類型的一個對象。看一下與該類相關的方法:
//在NSMethodSignature.h中
+ (nullable NSMethodSignature *)signatureWithObjCTypes:(const char *)types; //1
//在NSObject.h中
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE(""); //2
+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE(""); //3
2和3兩個方法是根據SEL來構造NSMethodSignature,而1方法則是今天的主角,那裡面的types究竟是什麼呢?
根據1的方法名稱可以猜想,types是ObjCTypes,它是一個是字元串數組,該數組包含了方法的類型編碼。那如果我們用該方法實例化NSMethodSignature的時候究竟如何寫types呢?先來舉個例子:
- (void)goToSchoolWithPerson:(Person *)person;
[zhangsan goToSchoolWithPerson:lisi];
其ObjcTypes就是 "v@:@"。那究竟是如何得來該字元串呢?其實我們有兩種方式:
- 直接查表。在Type Encodings裡面列出了對應關係。
- 使用 @encode()計算。( NSLog(@"%s",@encode(BOOL))的結果為B )
我們都知道消息發送會被轉換成objc _ msgSend(id reciever,SEL sel,prarams1,params2,....)。所以上面的方法會被轉換成:
void objc_msgSend(zhangsan,@selector(goToSchoolWithPerson:),lisi); //包含兩個隱藏參數
這裡的 “v@:@”就代表:
再舉個例子:
- (BOOL)ifSuccess:(NSString *)tag
其ObjCTypes為:"B@:@",其中:
- "B":代表BOOL。 // NSLog(@"%s",@encode(BOOL))的結果為B
- "@":一個id類型的對象,第一個參數類型,也就是objc _ msgSend的第一個參數
- ":":代表對應的SEL,第二個參數
- "@":一個id類型的對象,也就是tag。
到此,我們就知道了該如何書寫ObjCTypes了。