• <acronym id='nrjif'><em id='nrjif'></em><td id='nrjif'><div id='nrjif'></div></td></acronym><address id='nrjif'><big id='nrjif'><big id='nrjif'></big><legend id='nrjif'></legend></big></address>

    <dl id='nrjif'></dl>
      <i id='nrjif'></i>
    1. <tr id='nrjif'><strong id='nrjif'></strong><small id='nrjif'></small><button id='nrjif'></button><li id='nrjif'><noscript id='nrjif'><big id='nrjif'></big><dt id='nrjif'></dt></noscript></li></tr><ol id='nrjif'><table id='nrjif'><blockquote id='nrjif'><tbody id='nrjif'></tbody></blockquote></table></ol><u id='nrjif'></u><kbd id='nrjif'><kbd id='nrjif'></kbd></kbd>

      <code id='nrjif'><strong id='nrjif'></strong></code>

        <i id='nrjif'><div id='nrjif'><ins id='nrjif'></ins></div></i>

          <ins id='nrjif'></ins>

          1. <span id='nrjif'></span>
          2. <fieldset id='nrjif'></fieldset>

            深入理解Objective-C中类的数据结构

            • 时间:
            • 浏览:4
            • 来源:124软件资讯网

              一、类的结构

              OC 中的代码在底层实现  ,使用的是 C、C++ ,以是要研究 OC 中的类结构  ,可以将 OC 的代码转成 C++的代码即可 。首先看一下 NSObject 的结构是什么样子的  ,建立一个文件并简朴的编写如下代码:

              // CustomFile.m
              #import void test() {
               [NSObject alloc];
              }

              进入终端  ,输入指令:

              clang -rewrite-objc CustomFile.m

              默认天生一个 CustomFile.cpp 文件 。这个指令天生的代码会许多  ,也可以使用 xcrun 指令来指定一个特定的架构  ,这样的:

              xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc CustomFile.m -o CustomFile_arm64.cpp

              这样在 CustomFile_arm64.cpp 文件中会天生一个 真机下的运行代码  。相比之下 CustomFile_arm64.cpp 文件会比 CustomFile.cpp 小了许多 ,可是对于检察 NSObject 的现实结构都是可以的  。

              打开恣意一个 .cpp 文件 ,都可以找到这样的界说:

              struct NSObject_IMPL {
               Class isa;
              };

              其中 Class 的界说如下:

              typedef struct objc_class *Class;

              再来看一下在现实中的 NSObject 类的声明是什么样的:

              @interface NSObject  {
              #pragma clang diagnostic push
              #pragma clang diagnostic ignored "-Wobjc-interface-ivars"
               Class isa OBJC_ISA_AVAILABILITY;
              #pragma clang diagnostic pop
              }

              简化后是这样的:

              @interface NSObject {
               Class isa;
              }

              总之Class 是一个指针  ,NSObject_IMPL是一个结构体 ,与 NSObject 在结构上极为相似  。

              二、类继续后的结构

              建立一个 Person.m 文件 ,弄一个继续于 NSObject 的 Person 类  。代码编写如下:

              // Person.m
              #import  
              // 类的说明
              @interface Person : NSObject
              @end
               
              // 类的实现
              @implementation Person
              @end
               
              // 类的说明
              @interface Student : Person
              @end
               
              // 类的实现
              @implementation Student
              @end

              其中 Person 继续于 NSObject ,Student 继续于 Person 于是在 .cpp 文件中找到这样的界说:

              struct Person_IMPL {
               struct NSObject_IMPL NSObject_IVARS;
              };
               
              struct Student_IMPL {
               struct Person_IMPL Person_IVARS;
              };

              NSObject_IVARS 看着这个命名就可以猜到是将父类的所有 ivar 都继续过来了 。

              似乎明确了一个套路

              在 NSObject 中只有一个 Class 类型的成员变量 isa ,在没有自界说任何的成员属性的情形下  ,继续的子类中的 ivar 都来自于父类  。

              若是说给 Person 与 Student 都界说一个成员变量 ,是这样的:

              struct Person_IMPL {
               struct NSObject_IMPL NSObject_IVARS;
               int _no;
              };
               
              struct Student_IMPL {
               struct Person_IMPL Person_IVARS;
               int _age;
              };

              终于对 Class 的一些套路有进一步的明白了  。

              三、添加要领后的结构

              建立一个 FunClass.m 文件  ,编写代码如下:

              // FunClass.m
              #import  
              // 类的说明
              @interface FunClass : NSObject
              - (void)testInstance;
              + (void)testClass;
              @end
               
              // 类的实现
              @implementation FunClass
              - (void)testInstance {
                
              }
               
              + (void)testClass {
                
              }
              @end

              最后发现在 .cpp 中类的结构没有任何的改变  ,是这样的:

              struct FunClass_IMPL {
               struct NSObject_IMPL NSObject_IVARS;
              };

              可是我们会发现另外一个问题 ,在 OC 中的要领酿成这样的了:

              // 实例要领
              _OBJC_$_INSTANCE_METHODS_FunClass __attribute__ ((used, section ("__DATA,__objc_const"))) = {
               sizeof(_objc_method),
               1,
               {{(struct objc_selector *)"testInstance", "v16@0:8", (void *)_I_FunClass_testInstance}}
              static void _I_FunClass_testInstance(FunClass * self, SEL _cmd) {
              }
               
              // 类要领
              _OBJC_$_CLASS_METHODS_FunClass __attribute__ ((used, section ("__DATA,__objc_const"))) = {
               sizeof(_objc_method),
               1,
               {{(struct objc_selector *)"testClass", "v16@0:8", (void *)_C_FunClass_testClass}}
              static void _C_FunClass_testClass(Class self, SEL _cmd) {
               
              }

              发现这几个特点:

              1. 实例要领有这个:_INSTANCE_METHODS_FunClass  ,类要领的是这个:_CLASS_METHODS_FunClass

              2. 两个要领都是 static 要领

              3. 要领都多了两个参数:self 与_cmd ,这也回覆了为什么 self 与 _cmd 只能在要领中有的基础缘故原由  。

              关于 要领 的这部门先先容到这里  ,后期会有专门的专题 。