11.理解objc_msgSend作用
靜態綁定(static binding):在編譯期就能決定運行時所應調用的函數
動態綁定(dynamic binding):所調用的函數在運行期才能確定
void objc_msgSend(id self,SEL cmd,..)
- self:代表接收者
- SEL:代表@selector()
- ...:代表消息后續參數
流程
- 在接收者所屬的類中搜尋其“方法列表”,找到,則跳轉至實現代碼
- 找不到,沿著繼承體系向上查找,找到,再跳轉
- 還找不到,執行消息轉發(message forwarding)
其他函數
- objc_msgSend_stret:發送的消息返回結構體
- objc_msgSend_fpret:發送的消息返回浮點數
- objc-msgSendSuper:如果要給超類發消息
12.理解消息轉發機制
13.用“方法調配技術”調試“黑盒方法”
獲取方法實現:Method class_getInstanceMethod(Class cls, SEL name)
-
交換方法實現:void method_exchangeImplementations(Method m1, Method m2)
<pre><code>
-(void)example13{NSString *testStr = @"tesT the StRing";
NSString *lowercaseString = [testStr lowercaseString];
pr_obj(lowercaseString);
NSString *uppercaseString = [testStr uppercaseString];
pr_obj(uppercaseString);
Method originalMethod = class_getInstanceMethod([NSString class],
@selector(lowercaseString));Method swappedMethod = class_getInstanceMethod([NSString class],
@selector(uppercaseString));method_exchangeImplementations(originalMethod, swappedMethod);
lowercaseString = [testStr lowercaseString];
pr_obj(lowercaseString);
uppercaseString = [testStr uppercaseString];
pr_obj(uppercaseString);
}
</pre></code>
14.理解“類對象”的用意
- id:通用對象類型
如果聲明時指定具體類型,在該類實例中調用該類沒有的方法時,編譯器會警告,而id不會
- isMemberOfClass:判斷對象是否為某個類的實例,不包括父類和子類
- isKindOfClass:判斷對象是否為某個類的實例或其派生類的實例,包括父類,不包括子類
<pre><code>
pragma mark - Grandpa
@interface Grandpa : NSObject
@end
@implementation Grandpa
@end
pragma mark - Father
@interface Father : Grandpa
@end
@implementation Father
@end
pragma mark - Son
@interface Son : Father
@end
@implementation Son
@end
</pre></code>
<pre><code>
-(void)example14{
Father *father = [[Father alloc] init];
pr_int([father isMemberOfClass:[Grandpa class]]);
pr_int([father isMemberOfClass:[Father class]]);
pr_int([father isMemberOfClass:[Son class]]);
pr_int([father isKindOfClass:[Grandpa class]]);
pr_int([father isKindOfClass:[Father class]]);
pr_int([father isKindOfClass:[Son class]]);
}
</pre></code>