使用運行時前提,必須導入#import <objc/message.h>
1.runtime使用技巧
- 誰來發生動作,前綴就是誰。
- 讓編譯器有提示:設置為NO
TARGETS - Build Settings - 搜索msg - 改為NO
- 查看oc底層runtime的實現
cd 目錄
clang -rewrite-objc 文件名
2.1.對象如何找到對應方法去調用:
- 對象方法存放在類中,類方法存放在元類(meta class)中。
- 類調用的方法,在runtime底層,會把類轉化為類對象再調用方法。
- 每一個類都有一個方法列表(MethodList)(已實現的方法)。
1.根據isa指針找到所屬類
2.根據方法編號在方法列表中找到類中的方法名
3.根據方法名到方法區找到方法的實現
2.2.類如何找到類方法去調用:
- 元類保存了類方法列表
- 元類(meteClass)是類,也是對象
1.根據所屬類的isa指針找到元類
2.根據方法編號在類方法列表中找到類中的方法名
3.根據方法名到方法區找到方法的實現
4.如果沒有,向父元類查找實現
3.消息機制
Person *p = [[Person alloc] init];
//不帶參數
objc_msgSend(p, @selector(eat));
//帶參數
objc_msgSend(p, @selector(eat), 20);
4.交換方法
- 應用場景:系統方法原本的功能可能不夠用,保持原有功能擴展新的功能
- 分類中重寫load方法,在load方法中把系統原方法和新方法用runtime交換
+ (void)load
{
Method imageNamedMethod = class_getClassMethod(self, @selector(imageNamed:));
// 獲取xmg_imageNamed
Method xmg_imageNamedMethod = class_getClassMethod(self, @selector(xmg_imageNamed:));
// 交互方法:runtimec
method_exchangeImplementations(imageNamedMethod, xmg_imageNamedMethod);
}
5.添加方法
- 應用場景:懶加載機制,有些方法很久不會調用,加載類到內存很消耗資源,動態添加方法,就是用到的時候再加載到內存。
#import "ViewController.h"
#import "Person.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person *p = [[Person alloc] init];
[p performSelector:@selector(eat)];
[p performSelector:@selector(run:) withObject:@1];
}
@end
#import "Person.h"
#import <objc/message.h>
@implementation Person
+ (BOOL)resolveInstanceMethod:(SEL)sel{
if(sel == NSSelectorFromString(@"eat")){
class_addMethod(self, sel, (IMP)eat, "v@:@");
return YES;
}
if(sel == NSSelectorFromString(@"run:")){
class_addMethod(self, sel, (IMP)(run), "v@:@");
return YES;
}
return [super resolveInstanceMethod:sel];
}
void eat(id self, SEL _cmd){
NSLog(@"吃了嗎您那?");
}
void run(id self, SEL _cmd, NSNumber *num){
NSLog(@"跑了%@米", num);
}
@end
6.添加屬性:
- 運用場景:給系統的類添加屬性
6.1.生成分類
6.2.重寫set get方法
@interface NSObject (Property)
@property NSString *name;
@end
- (void)setName:(NSString *)name{
objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)name{
return objc_getAssociatedObject(self, @"name");
}
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。