Runtime:
runtime底層方法調(diào)用无午,正常項目中OC 是不希望你去調(diào)用底層代碼的瘪松,所以我們需要修改下配置文件(build settings 搜查msg 將bool修改為NO),之后創(chuàng)建一個Person類,并且創(chuàng)建一個eat方法?
具體實現(xiàn):https://github.com/liyunhe/RuntimeStudy
#import"Person.h"@implementationPerson-(void)eat{
? ? NSLog(@"調(diào)用我了");
}@end
利用 objc_msgSend調(diào)用eat方法
Person *p = [[Person alloc] init];
? objc_msgSend(p, @selector(eat));
下面我們嘗試不適用OC 上層代碼調(diào)用具體代碼如下
//創(chuàng)建對象NSObject* p = objc_msgSend(objc_msgSend(objc_getRequiredClass("Person"),@selector(alloc)),@selector(init)); ?//調(diào)用方法objc_msgSend(p,@selector(eat));
驗證是否是底層代碼?
1.創(chuàng)建一個command line Lauguage 選中OC??
2.利用終端cd到main.c所在目錄?
3.執(zhí)行clang -rewrite-objc main.m??
4.找到main.cpp?
如下是OC 底層實現(xiàn)代碼
int main(int argc, const char * argv[]) {
? ? /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
? ? ? ? Person * p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("alloc")), sel_registerName("init"));
? ? ? ? NSLog((NSString *)&__NSConstantStringImpl__var_folders_7s_75jn6mvs2_xfh3v7hmq7v0140000gn_T_main_2edfc3_mi_0);
? ? }
? ? return 0;
}
方法交換
當項目中需要大的修改 或者某個方法有存在問題一般會用到?
項目中如果url不符合規(guī)則就會url =nil,下面為URLWithString 添加一個篩選條件可以更清楚地定位到問題悠瞬,為系統(tǒng)類的方法添加工程我們一般都會使用擴展類们豌。添加NSURL+Url.H
NSURL * url = [NSURL URLWithString:@"中文"];
具體代碼:
#import"NSURL+Url.h"#import@implementationNSURL(Url)//+(instancetype)URLWithString:(NSString *)URLString{//}+(instancetype)YH_URLWithStr:(NSString *)str{
? ? NSURL *url = [NSURL YH_URLWithStr:str];
? ? if (url==nil) {
? ? ? ? NSLog(@"url為Nil");
? ? }
? ? return url;
}
+(void)load{
? ? //交換方法? ? //method 成員方法//? ? class_getClassMethod 獲取類方法//? ? class_getInstanceMethod 獲取靜態(tài)方法? ? Method urlWithUrl = class_getClassMethod(self, @selector(URLWithString:));
? ? Method YH_URLWithStr = class_getClassMethod(self, @selector(YH_URLWithStr:));
? ? method_exchangeImplementations(urlWithUrl, YH_URLWithStr);
}