先看一下消息轉(zhuǎn)發(fā)流程:

消息轉(zhuǎn)發(fā)流程
在forwardInvocation這一步,你必須要實(shí)現(xiàn)一個(gè)方法:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("");
該方法用于說(shuō)明消息的返回值和參數(shù)類(lèi)型。NSMethodSignature是方法簽名,它是用來(lái)記錄返回值和參數(shù)類(lèi)型的一個(gè)對(duì)象??匆幌屡c該類(lèi)相關(guān)的方法:
//在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兩個(gè)方法是根據(jù)SEL來(lái)構(gòu)造NSMethodSignature,而1方法則是今天的主角,那里面的types究竟是什么呢?
根據(jù)1的方法名稱可以猜想,types是ObjCTypes,它是一個(gè)是字符串?dāng)?shù)組,該數(shù)組包含了方法的類(lèi)型編碼。那如果我們用該方法實(shí)例化NSMethodSignature的時(shí)候究竟如何寫(xiě)types呢?先來(lái)舉個(gè)例子:
- (void)goToSchoolWithPerson:(Person *)person;
[zhangsan goToSchoolWithPerson:lisi];
其ObjcTypes就是 "v@:@"。那究竟是如何得來(lái)該字符串呢?其實(shí)我們有兩種方式:
- 直接查表。在Type Encodings里面列出了對(duì)應(yīng)關(guān)系。
- 使用 @encode()計(jì)算。( NSLog(@"%s",@encode(BOOL))的結(jié)果為B )
我們都知道消息發(fā)送會(huì)被轉(zhuǎn)換成objc _ msgSend(id reciever,SEL sel,prarams1,params2,....)。所以上面的方法會(huì)被轉(zhuǎn)換成:
void objc_msgSend(zhangsan,@selector(goToSchoolWithPerson:),lisi); //包含兩個(gè)隱藏參數(shù)
這里的 “v@:@”就代表:
- "v":代表返回值void
- "@":代表一個(gè)對(duì)象,這里指代的id類(lèi)型zhangsan,也就是消息的receiver
- ":":代表SEL
- "@":代表參數(shù)lisi
再舉個(gè)例子:
- (BOOL)ifSuccess:(NSString *)tag
其ObjCTypes為:"B@:@",其中:
- "B":代表BOOL。 // NSLog(@"%s",@encode(BOOL))的結(jié)果為B
- "@":一個(gè)id類(lèi)型的對(duì)象,第一個(gè)參數(shù)類(lèi)型,也就是objc _ msgSend的第一個(gè)參數(shù)
- ":":代表對(duì)應(yīng)的SEL,第二個(gè)參數(shù)
- "@":一個(gè)id類(lèi)型的對(duì)象,也就是tag。
到此,我們就知道了該如何書(shū)寫(xiě)ObjCTypes了。