iOS Runtime詳細解のSEL、Class、id、IMP、_cmd,isa,method,Ivar


オリジナルBlog、転載は出所を明記してください.http://blog.csdn.net/hello_hwc?view mode=list私のstackover flow
前書き:こんなに長いiOSブログを書いても、ルumtimeを書く時があります.実際に開発に使うシーンが多いです.
  • 動的変更方法の実行体
  • Method Swizling
  • NSSelectorFroomString、NSClass FroomString…
  • 動的追加属性(主にカテゴリ)
  • は、属性と方法を動的に遍歴し、動的にクラス追加方法
  • である.
    しかし、基本的な概念はとても重要で、Runtimeのこのシリーズの計画のいくつかの文章を計画します.
  • はいくつかの基本概念(本文)を講義します.例えば、SEL、Class、id、IMPなどの
  • です.
  • は、iOSにおけるメッセージの伝達機構、およびメッセージ転送機構、メモリ割り当て、クラスオブジェクト、クラスオブジェクト
  • を詳細に理解する.
  • Method Swizling
  • その他の一般的な実用的なアプリケーション
  • Runtimeとは
    Objective C言語は運行期間でできることを運行期間に延期して決定します.これはObjective Cにコンパイラが必要なだけでなく、運行期間環境が必要なことを意味します.この運行期間の環境はRuntimeです.
    最も直接的な例は、このようなOCメソッドを呼び出す方法です.
    [receiver message]
    コンパイルされます
    objc_msgSend(receiver, selector)
    ここで、まずreceiverが受信メッセージの対象であり、selectorは実行メッセージの関数名であり、Cの文字列であることを覚えている.他の言語のように直接的にコンパイルして関数体のポインタを指します.
    では、運行する時に、どうやってobjcを通過しますか?msgSend(receiver,selector)は実際の関数体を探しますか?
    That is Runtime
    なぜこのような基礎的な文章を書くのですか?
    最初にRuntimeに接触した時、感覚が乱れていました.最後に考えましたが、主にいくつかの基本概念がよく分かりません.これらの名詞はほとんど理解と応用が不可能です.
    だから、私がRuntimeについて説明する方法は、まず基本的なキーワードの底の定義を明確にし、その後、メッセージ処理と転送メカニズムを説明し、最後に例を説明することです.
    SEL/objc_selector
    OBselector
    透明なデータ構造は、C Stringとして理解できる.
    SELソースコード定義
    typedef struct objc_selector *SEL;
    
    つまり、SELはC Stringを指すポインタです.
    id/objc_object
    ID-クラスを指す例示的なオブジェクトの下のコード定義
    typedef struct objc_object *id;
    その中のobjc_objectの底の定義
    struct objc_object {
        Class isa  OBJC_ISA_AVAILABILITY;
    };
    見られますobjectの中で、ただ1つのクラスのタイプのisaだけを保存しました.ここでは読めないので、怖がらずに覚えておきます.対象の中にはObjective Cに対応する種類の指針が保存されています.
    Class/objc_クラス
    Class-Objective C類の対象を指す一つのポインタの底に定義されています.
    typedef struct objc_class *Class;
    OBクラスの底の定義
    struct objc_class {
        Class isa  OBJC_ISA_AVAILABILITY;
    
    #if !__OBJC2__
        Class super_class                                        OBJC2_UNAVAILABLE;
        const char *name                                         OBJC2_UNAVAILABLE;
        long version                                             OBJC2_UNAVAILABLE;
        long info                                                OBJC2_UNAVAILABLE;
        long instance_size                                       OBJC2_UNAVAILABLE;
        struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
        struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
        struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
        struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
    #endif
    
    } OBJC2_UNAVAILABLE;
    /* Use `Class` instead of `struct objc_class *` */
    
    これはクラスのオブジェクト構造体の定義です.細かいクラスメイトはクラスのオブジェクトの中にまだ一つの指針Class isaがあることを発見したかもしれません.まず覚えておきます.このisaはクラスのオブジェクトを指しています.これは次の文章で詳しく述べます.
    IMP
    IMP-実際の実行関数の関数ポインタを指します.
    #if !OBJC_OLD_DISPATCH_PROTOTYPES
    typedef void (*IMP)(void /* id, SEL, ... */ ); 
    #else
    typedef id (*IMP)(id, SEL, ...); 
    #endif
    この関数の最初の2つのパラメータはID(メッセージ受信者、つまりオブジェクト)とSEL(メソッドの名前)であることがわかる.
    method/objc_method
    method-Objective Cにおける方法の指針を指す.
    typedef struct objc_method *Method;
    そのうち
    struct objc_method {
        SEL method_name                                          OBJC2_UNAVAILABLE;
        char *method_types                                       OBJC2_UNAVAILABLE;
        IMP method_imp                                           OBJC2_UNAVAILABLE;
    }                                                            OBJC2_UNAVAILABLE;
    
    _.cmd
    SELタイプの一つの変数、Objective Cの関数の最初の二つの隠しパラメータはselfと_です.cmd
    Ivar
    ivar-objective Cにおける例示的変数
    typedef struct objc_ivar *Ivar;
    
    変数のメモリモデルが見られます.
    struct objc_ivar {
        char *ivar_name                                          OBJC2_UNAVAILABLE;
        char *ivar_type                                          OBJC2_UNAVAILABLE;
        int ivar_offset                                          OBJC2_UNAVAILABLE;
    #ifdef __LP64__
        int space                                                OBJC2_UNAVAILABLE;
    #endif
    }                                                            OBJC2_UNAVAILABLE;