Runtime-原理與應用

使用運行時前提,必須導入#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");
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 轉至元數據結尾創建: 董瀟偉,最新修改于: 十二月 23, 2016 轉至元數據起始第一章:isa和Class一....
    40c0490e5268閱讀 1,757評論 0 9
  • 對于從事 iOS 開發人員來說,所有的人都會答出【runtime 是運行時】什么情況下用runtime?大部分人能...
    夢夜繁星閱讀 3,732評論 7 64
  • 這篇文章完全是基于南峰子老師博客的轉載 這篇文章完全是基于南峰子老師博客的轉載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,585評論 33 466
  • 目錄 Objective-C Runtime到底是什么 Objective-C的元素認知 Runtime詳解 應用...
    Ryan___閱讀 1,950評論 1 3
  • 影片一開始,幾米《向左走?向右走》的故事情節閃過腦海,隨之被片頭曲驅散——這曲風轉換得讓耳朵有點跟不上節奏。 整部...
    蘿卜閱讀 362評論 2 1