欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Objective-C中類的數(shù)據(jù)結構是怎么樣的

小編給大家分享一下Objective-C中類的數(shù)據(jù)結構是怎么樣的,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務領域包括:成都網(wǎng)站設計、網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務,滿足客戶于互聯(lián)網(wǎng)時代的六合網(wǎng)站設計、移動媒體設計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡建設合作伙伴!

一、類的結構

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

// 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 在結構上極為相似。

二、類繼承后的結構

創(chuàng)建一個 Person.m 文件,弄一個繼承于 NSObject 的 Person 類。代碼編寫如下:

// Person.m
#import <Foundation/Foundation.h>

// 類的申明
@interface Person : NSObject
@end

// 類的實現(xiàn)
@implementation Person
@end

// 類的申明
@interface Student : Person
@end

// 類的實現(xiàn)
@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 的一些套路有進一步的理解了。

三、添加方法后的結構

創(chuàng)建一個 FunClass.m 文件,編寫代碼如下:

// FunClass.m
#import <Foundation/Foundation.h>

// 類的申明
@interface FunClass : NSObject
- (void)testInstance;
+ (void)testClass;
@end

// 類的實現(xiàn)
@implementation FunClass
- (void)testInstance {
 
}

+ (void)testClass {
 
}
@end

最后發(fā)現(xiàn)在 .cpp 中類的結構沒有任何的改變,是這樣的:

struct FunClass_IMPL {
 struct NSObject_IMPL NSObject_IVARS;
};

但是我們會發(fā)現(xiàn)另外一個問題,在 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) {

}

發(fā)現(xiàn)這幾個特點:

     1、實例方法有這個:_INSTANCE_METHODS_FunClass,類方法的是這個:_CLASS_METHODS_FunClass

     2、兩個方法都是 static 方法

     3、方法都多了兩個參數(shù):self 與_cmd,這也回答了為什么 self 與 _cmd 只能在方法中有的根本原因。

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

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

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

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

// ==== 類的定義部分 ====
// 類的申明
@interface HGNObject : NSObject {
 @public
 int _no;
 int _age;
}
@end

// 類的實現(xiàn)
@implementation HGNObject
@end

// ==== 結構體 ====
struct HGNObject_IMPL {
 Class isa_hg;
 int _no_hg;
 int _age_hg;
};

做兩個試驗:

1、類轉(zhuǎn)結構體

2、結構體轉(zhuǎn)類

1、類轉(zhuǎn)結構體

示例代碼如下:

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

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

2、結構體轉(zhuǎn)類

示例代碼如下:

// 結構體轉(zhuǎn)類
- (void)struct2Class {
 NSLog(@"結構體轉(zhuǎn)類");
 // 生成一個結構體
 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;
 
 // 結構體轉(zhuǎn)成對象
 HGNObject* nObj = (__bridge HGNObject *)(nObj_sPointer);
 
 NSLog(@"_no_hg = %zd, _age_hg = %zd", nObj->_no, nObj->_age);
}

運行代碼,直接 crash 了:

Objective-C中類的數(shù)據(jù)結構是怎么樣的

由于 Block 解開多年來的誤解 的慘痛教訓,所以對遇到的 crash 就會很敏感。看一下上面的這張圖,有一個關鍵的點是不可以忽視的,就是這里的值:

Objective-C中類的數(shù)據(jù)結構是怎么樣的

以上是“Objective-C中類的數(shù)據(jù)結構是怎么樣的”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

本文名稱:Objective-C中類的數(shù)據(jù)結構是怎么樣的
分享URL:http://chinadenli.net/article32/ipgssc.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供建站公司企業(yè)網(wǎng)站制作響應式網(wǎng)站網(wǎng)站建設網(wǎng)站導航定制開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名