Runtimeランタイム1:クラス

5242 ワード

概要Objective-C言語は動的言語であり、多くの静的言語がコンパイルとリンクの時期にしたことを実行時に処理します.
この特性は、Objective-Cがコンパイラだけでなく、コンパイルされたコードを実行するためにランタイムシステムも必要であることを意味する.Objective-Cでは、このランタイムシステムはオペレーティングシステムのように動作します.これにより、すべての動作が正常に動作します.このランタイムシステムはObjc Runtimeです.Objc Runtimeは実はRuntimeライブラリで、基本的にはCとアセンブリで書かれており、このライブラリはC言語にオブジェクト向けの能力を持たせた.
objc_object objc_objectはクラスの一例を示す構造体である
struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};
  • isaポインタが属するクラスを指すことから、この構造体には1つのフォント、すなわちインスタンスが属するクラスを指すisaポインタしかないことがわかる.Objective-Cオブジェクトにメッセージを送信すると、実行時ライブラリはインスタンスオブジェクトのisaポインタに基づいてこのインスタンスオブジェクトが属するクラスを見つけます.Runtimeライブラリは、クラスのメソッドリストおよび親クラスのメソッドリストで、メッセージに対応するselectorが指すメソッドを探します.見つけたらこの方法を実行します.

  • Class Objective-Cクラスは、Classタイプによって表され、実際にはobjc_class構造体を指すポインタであり、つまりClass自体もオブジェクトであることを意味する.定義は次のとおりです.
    typedef struct objc_class *Class;
    
    struct objc_class {
        Class isa  OBJC_ISA_AVAILABILITY;
    #if !__OBJC2__
        Class super_class                       OBJC2_UNAVAILABLE;  //   
        const char *name                        OBJC2_UNAVAILABLE;  //   
        long version                            OBJC2_UNAVAILABLE;  //       ,   0
        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;
    
  • isaポインタはMeta Class(メタクラス)を指し、クラスもオブジェクトである以上、objc_objectポインタであり、クラスを指すisaポインタを含む.では、これらには問題があります.このisaポインタは何を指していますか.クラスメソッドを呼び出すために、このクラスのisaポインタは、これらのクラスメソッドを含むobjc_class構造体を指さなければならない.これはMeta Classの概念
  • を引き出した.
    Meta Class Meta Classは、クラスのすべてのクラスメソッドを格納するクラスオブジェクトのクラスです.
  • isaポインタはベースクラスMeta Classを指します.Meta Classもクラスである以上、メッセージを送信することもできます.では、isaは何を指していますか.このような構造が無限に延びないように、Objective-Cの設計者は、すべてのMeta ClassisaをベースクラスのMeta Classに指向させ、それらの所属クラスとする.すなわち、任意のNSObject継承システムの下のMeta Classは、NSObjectMeta Classを自分の属するクラスとして使用し、ベースクラスのMeta Classisaポインタはそれ自身を指す.これで完璧な閉ループが形成された.

  • 動的生成Objective-Cが動的言語である以上、すべては実行時に動的に作成できます.
    クラスの作成
    パラメータ1:親パラメータ2:名前パラメータ3:開バイト長
    Class Student = objc_allocateClassPair([Person class], "Student", 0);
    

    メンバー変数の作成
    パラメータ1:クラス名パラメータ2:名前パラメータ3:バイト長パラメータ4:メモリ整列パラメータ5:パラメータタイプ"@"公式解釈An object(whether statically typed or typed id)(オブジェクト静的タイプまたはidタイプ)具体的なタイプ参照可能官方ドキュメント
    class_addIvar(Student, "_studentID", sizeof(NSString *), log2(sizeof(NSString *)), "^NSString");
    class_addIvar(Student, "_classNumber", sizeof(NSInteger), log(sizeof(NSInteger)), "i");
    

    属性の作成
    属性カテゴリの説明
    objc_property_attribute_t type = {"T", "@\"NSString\""}; //   
    objc_property_attribute_t iver = {"V", "_studentID"}; //        
    objc_property_attribute_t ownership = {"C", ""}; //      
    objc_property_attribute_t nonatomic = {"N", ""};//    
            
    objc_property_attribute_t attributes[] = {type, iver, ownership, nonatomic};
            
    //           ,@1   , @2:    , @3:         
    class_addProperty(Student, "sid", attributes, 4);
    

    作成方法
    パラメータ1、クラス名パラメータ2、SELに追加されたメソッド名パラメータ3、IMPポインタ(IMPはImplementationの略であり、一つのメソッド実装を指すポインタであり、それぞれのメソッドに対応するIMPがある)パラメータ4、ここでtypesパラメータは「i@:@」であり、具体的なタイプは公式文書iの戻り値タイプintを参照し、vであればvoid@パラメータid(self):SEL(_cmd)@id(str)V@:戻り値がvoidにSELパラメータ(An object(wheter statically typed or typed)があることを示す.
    class_addMethod(Student, @selector(test:), (IMP)test, "v@:^NSString");
    

    ここでは関数と方法を実現する必要があります
    void test(id self, SEL _cmd, NSString *str) {
        //       
    }
    
    - (void)test:(NSString *)str {
        NSLog(@"%@", str);
    }
    

    オブジェクトの作成
    オブジェクトを作成するにはシステムに登録する必要があります
    objc_registerClassPair(Student);
    

    メンバー変数の作成方法と同じですが、パラメータのタイプが異なります.
    BOOL isSuccess = class_addIvar(Student, "studentOne", sizeof(NSString *), 0, "@");
    

    メンバー変数の割当て#メンバーヘンスウノワリアテ#
    //           
    Ivar ivar = class_getInstanceVariable(Student, "_studentID");
    //        
    object_setIvar(studentOne, ivar, @"4321");
    //         
    id value = object_getIvar(studentOne, ivar);
    

    属性の取得
    //     
    objc_property_t property = class_getProperty(Student, "sid");
    //        
    const char *pName = property_getName(property);
    //       
    const char *pAtrributes = property_getAttributes(property);