亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

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

2019-10-21 18:41:07
字體:
來源:轉載
供稿:網友

一、類的結構

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 與對應的結構體

上面啰嗦了這么多,到底是對不對呢?!那就來親自試一下吧。

這里的自定義是指不再繼承于 NSObject 了,自己搞一個結構體。為了證明其正確性,分別定義一個 HGNObject 類 與 HGNObject_IMPL 結構體。編寫的代碼如下:

// ==== 類的定義部分 ====// 類的申明@interface HGNObject : NSObject { @public int _no; int _age;}@end// 類的實現@implementation HGNObject@end// ==== 結構體 ====struct HGNObject_IMPL { Class isa_hg; int _no_hg; int _age_hg;};

做兩個試驗:

1、類轉結構體

2、結構體轉類

1、類轉結構體

示例代碼如下:

// 類轉結構體- (void)class2Struct { // 創建一個對象 HGNObject* nObj = [[HGNObject alloc] init]; // 成員變量賦值 nObj->_no = 771722918; nObj->_age = 18;  { // 類對象直接轉成一個結構體 struct HGNObject_IMPL* nObj_s = (__bridge struct HGNObject_IMPL*)nObj; // 打印結構體中的值 NSLog(@"%zd, %zd", nObj_s->_no_hg, nObj_s->_age_hg); // 打印結果: 771722918, 18 }}

通過結構體指針能打印出在類對象中設置的值,說明在 類轉結構體的過程是有效的。

2、結構體轉類

示例代碼如下:

// 結構體轉類- (void)struct2Class { NSLog(@"結構體轉類"); // 生成一個結構體 struct HGNObject_IMPL nObj_s = {0, 771722918, 20}; // 結構體中的值打印 NSLog(@"isa_hg = %zd, _no_hg = %zd, _age_hg = %zd", nObj_s.isa_hg, nObj_s._no_hg, nObj_s._age_hg);  struct HGNObject_IMPL* nObj_sPointer = &nObj_s;  // 結構體轉成對象 HGNObject* nObj = (__bridge HGNObject *)(nObj_sPointer);  NSLog(@"_no_hg = %zd, _age_hg = %zd", nObj->_no, nObj->_age);}

運行代碼,直接 crash 了:

Objective-C,數據結構

由于 Block 解開多年來的誤解 的慘痛教訓,所以對遇到的 crash 就會很敏感??匆幌律厦娴倪@張圖,有一個關鍵的點是不可以忽視的,就是這里的值:

Objective-C,數據結構

簡單的分析(我這里的分析都是猜的,暫時我也不知道,【抱歉抱歉抱歉】)

nObj_s 是有正確的值的,說明 nObj_sPointer 指針也是沒有問題的,但是為什么會報一個壞地址訪問錯誤呢?并且 address 的值每次都是一樣的 0x20。我猜想:在轉化的過程中不僅僅是一個簡單的賦值操作、可能還做了其他的地址訪問操作,這個操作很有可能與 +alloc 方法中操作有關,畢竟在 OC 中正常的創建一個對象必先 +alloc方法,對于 +alloc中都做了什么事,暫時我還不清楚,所以這里我是蒙的。各位大神若有新的理解,望指教!

所以在第一個實驗中的 類轉結構體 中是有效的,也許是一個偶然。畢竟我們在上面的 .cpp 文件中查看數據結構的時候也只是看了一個大概,并沒有看全部的。

OK,忘記本節(自定義一個 Class 與對應的結構體)中遇到的不愉快, 至少 類轉結構體 是有效的,也能說明一些問題。

本系列的文章,有:

1、Objective-C 中類的數據結構

2、Objective-C 中實例所占內存的大小

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到IOS開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲一区av在线播放| 久久久久久久成人| 亚洲精品小视频| 久久影院资源站| 欧美猛交ⅹxxx乱大交视频| 精品人伦一区二区三区蜜桃网站| 日本19禁啪啪免费观看www| 亚洲人av在线影院| 久久香蕉精品香蕉| 4388成人网| 色偷偷av亚洲男人的天堂| 日韩精品亚洲视频| 尤物精品国产第一福利三区| 国产精品电影网站| 国产成人a亚洲精品| 91精品啪aⅴ在线观看国产| 日本欧美黄网站| 国产偷国产偷亚洲清高网站| 亚洲男人的天堂在线| 国产精品日日做人人爱| 久久99热精品这里久久精品| 久久久久久国产三级电影| 亚洲图片制服诱惑| 亚洲国产成人爱av在线播放| 亚洲人成电影网站色| 久久99精品国产99久久6尤物| 琪琪亚洲精品午夜在线| 欧美高跟鞋交xxxxhd| 日韩欧美在线观看| 91网在线免费观看| 国模精品一区二区三区色天香| 国语自产精品视频在线看| 亚洲欧美制服丝袜| 久久久久九九九九| 亚洲福利视频网| 国产在线高清精品| 日韩av在线播放资源| 国产97免费视| 亚洲欧美在线播放| 在线观看亚洲区| 国内精品美女av在线播放| 97在线免费观看| 欧美专区在线视频| 96sao精品视频在线观看| 成人黄色免费看| 久久久视频精品| 久久91亚洲人成电影网站| 久久精品中文字幕免费mv| 亚洲人a成www在线影院| 欧美激情一级欧美精品| 欧美成年人视频| 久99九色视频在线观看| 97精品国产aⅴ7777| 国产日韩精品在线| 亚洲欧美激情在线视频| 亚洲自拍小视频| 国产精品最新在线观看| 国产精品美女久久久免费| 成人性生交大片免费看视频直播| 成人欧美一区二区三区黑人孕妇| 97人人做人人爱| 91精品国产综合久久香蕉922| 久久久久久久久久久亚洲| 热门国产精品亚洲第一区在线| 日韩av在线一区二区| 日韩国产高清视频在线| 欧美视频二区36p| 国产脚交av在线一区二区| 成人av色在线观看| 久久久久久久久中文字幕| 日韩av片永久免费网站| 在线观看日韩专区| 国产精品91视频| 亚洲第一区中文99精品| 国产精品午夜国产小视频| 久久亚洲精品毛片| 国产精品亚洲精品| 国产91色在线免费| 亚洲精品国产精品国自产在线| 久久av.com| 精品日本高清在线播放| 色中色综合影院手机版在线观看| 97成人在线视频| 久久久成人精品视频| 91亚洲永久免费精品| 亚洲欧美日韩精品久久亚洲区| 日本欧美一二三区| 成人高清视频观看www| 日韩免费中文字幕| 欧美激情中文字幕乱码免费| 4k岛国日韩精品**专区| 欧美贵妇videos办公室| 亚洲国产成人精品一区二区| 伊人亚洲福利一区二区三区| 午夜精品一区二区三区在线视频| 一区二区三区 在线观看视| 91在线观看免费| 正在播放欧美一区| 欧日韩在线观看| 操91在线视频| 欧美老少做受xxxx高潮| 欧美性猛交xxxxx免费看| 欧美诱惑福利视频| 日韩欧美在线视频观看| 亚洲人成电影网站色xx| 亚洲国产精品久久| 国产精品大片wwwwww| 狠狠色狠狠色综合日日五| 久99久在线视频| 国产欧美欧洲在线观看| 国产日韩欧美日韩大片| 欧美精品精品精品精品免费| 欧美极品美女视频网站在线观看免费| 欧美性xxxx18| 国产日韩欧美在线视频观看| 亚洲国产精品成人va在线观看| 日韩成人在线播放| 91精品国产91久久久久福利| 国产精品成人在线| 91精品国产高清自在线看超| 69久久夜色精品国产69乱青草| 国产视频丨精品|在线观看| 91产国在线观看动作片喷水| 奇米4444一区二区三区| 国产精品2018| 在线观看亚洲区| 在线视频国产日韩| 国产视频精品免费播放| 精品久久久久久久久国产字幕| 国产日韩换脸av一区在线观看| 国产精品男人的天堂| www.亚洲免费视频| 国产成人精品视频在线| 精品久久久久久中文字幕一区奶水| 国产精品嫩草影院久久久| 日韩女优在线播放| 亚洲福利在线视频| 中文字幕无线精品亚洲乱码一区| 在线日韩中文字幕| 成人a在线视频| 久久精品国产亚洲| 亚洲影影院av| 国产欧美日韩中文字幕在线| 黄网站色欧美视频| 国产精品一区二区久久国产| 精品国内自产拍在线观看| 欧美又大粗又爽又黄大片视频| 国产偷国产偷亚洲清高网站| 亚洲在线视频观看| 国产精品r级在线| 久久久久国产视频| 亚洲丁香久久久| 亚洲va久久久噜噜噜| 国产剧情久久久久久| 亚洲国产高清福利视频| 欧美激情在线观看视频| 尤物yw午夜国产精品视频明星| 亚洲午夜未删减在线观看| 免费99精品国产自在在线| 中文字幕亚洲欧美| 日韩精品在线看| 亚洲无线码在线一区观看| 中文一区二区视频| 精品偷拍一区二区三区在线看|