国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

深入理解Objective-C中類的數據結構

2020-07-26 02:27:30
字體:
來源:轉載
供稿:網友

一、類的結構

OC 中的代碼在底層實現,使用的是 C、C++,所以要研究 OC 中的類結構,可以將 OC 的代碼轉成 C++的代碼即可。首先看一下 NSObject 的結構是什么樣子的,創建一個文件并簡單的編寫如下代碼:

// CustomFile.m#import <Foundation/Foundation.h>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 <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 <Foundation/Foundation.h>// 類的申明@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 <Foundation/Foundation.h>// 類的申明@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 只能在方法中有的根本原因。

關于 方法 的這部分先介紹到這里,后期會有專門的專題。

四、自定義一個 Class 與對應的結構體

上面

主站蜘蛛池模板: 龙陵县| 孝义市| 伊宁市| 青海省| 桓仁| 宜春市| 抚松县| 延安市| 岳西县| 宕昌县| 清镇市| 昭苏县| 澄城县| 丰宁| 拜泉县| 齐齐哈尔市| 青州市| 潼南县| 乌拉特前旗| 达拉特旗| 西充县| 西平县| 法库县| 资阳市| 安泽县| 奉新县| 温宿县| 体育| 黄陵县| 万盛区| 班戈县| 喀喇沁旗| 霍山县| 林甸县| 徐州市| 乌拉特前旗| 临洮县| 乌鲁木齐市| 于都县| 沙坪坝区| 旬邑县|