Runtime-原理と応用

2825 ワード

実行時前提で#importをインポートする必要があります

1.runtimeの使い方

  • 誰が動作し、接頭辞は誰ですか.
  • コンパイラにヒントを与える:NO TARGETS - Build Settings - msg - NO
  • に設定する.
  • oc最下位runtimeの実装cd clang -rewrite-objc
  • を参照

    2.1.オブジェクトがどのように対応するメソッドを見つけて呼び出すか:

  • オブジェクトメソッドはクラスに格納され、クラスメソッドはメタクラスに格納されます.
  • クラス呼び出しのメソッドはruntimeの下部でクラスをクラスオブジェクトに変換してメソッドを呼び出します.
  • 各クラスにはメソッドリスト(実装済みメソッド)があります.
  • 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 
    
    @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");
    }