欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:iOS——分類、擴(kuò)展和關(guān)聯(lián)對象

柚子快報激活碼778899分享:iOS——分類、擴(kuò)展和關(guān)聯(lián)對象

http://yzkb.51969.com/

前情回顧

回顧一下什么是分類、什么是擴(kuò)展: 分類(Category)和類擴(kuò)展(Extension)是兩種常見的代碼組織方式,用于擴(kuò)展類的功能。

分類(Category)

分類是一種將類的實現(xiàn)分散到多個源文件的方式。通過使用分類,你可以將一個類的實現(xiàn)分散到多個源文件中。分類可以為現(xiàn)有的類添加新的方法,這使得你可以向現(xiàn)有的類添加自己的方法。 分類不能添加實例變量,只能添加方法。 分類的特性是可以在運行時階段動態(tài)的為已有的類添加新行為。 分類就是對裝飾模式的一種具體實現(xiàn)。它的主要作用是在不改變原有類的前提下,動態(tài)地給這個類添加一些方法。 分類也可以把framework私有方法公開化

現(xiàn)在我們通過源碼看一下分類:

struct _category_t {

const char *name; // 分類的名稱

struct _class_t *cls; // 分類所屬的類

const struct _method_list_t *instance_methods; // 分類中定義的實例方法列表

const struct _method_list_t *class_methods; // 分類中定義的類方法列表

const struct _protocol_list_t *protocols; // 分類實現(xiàn)的協(xié)議列表

const struct _prop_list_t *properties; // 分類中定義的屬性列表

};

extern "C" __declspec(dllimport) struct objc_cache _objc_empty_cache;

從結(jié)構(gòu)體可以知道,分類可以添加屬性,但是只會生成這些屬性的getter和setter方法的聲明,并不會自動實現(xiàn)這些方法。也就是說,如果你在分類中添加了一個屬性,你還需要自己去實現(xiàn)這個屬性的getter和setter方法。分類不像類,它沒有成員變量列表,所以你不能在分類中添加成員變量。分類中的方法可以在運行時動態(tài)改變,但結(jié)構(gòu)體不能。如果你想要在運行時給原來的結(jié)構(gòu)體添加一個屬性,你只能通過關(guān)聯(lián)對象的方式。關(guān)聯(lián)對象的本質(zhì)是在類的定義之外為類增加額外的存儲空間,實現(xiàn)了一種映射關(guān)系。

擴(kuò)展(Extension)

類擴(kuò)展與分類類似,有時候也被稱為匿名分類,但是類擴(kuò)展可以添加實例變量和屬性。與分類不同,類擴(kuò)展的方法和屬性必須在類的主實現(xiàn)文件中實現(xiàn)。擴(kuò)展中聲明的所有方法和屬性必須在主類中實現(xiàn),否則會導(dǎo)致編譯錯誤。此外,類擴(kuò)展中添加的實例變量默認(rèn)為@private類型,其使用范圍只能在自身類中。 擴(kuò)展是在編譯階段與該類同時編譯的,是類的一部分。擴(kuò)展中聲明的方法只能在該類的@implementation中實現(xiàn)。所以這也就意味著我們無法對系統(tǒng)的類使用擴(kuò)展。

分類和擴(kuò)展的區(qū)別

分類原則上只能增加方法,但是也可以通過關(guān)聯(lián)屬性增加屬性拓展可以增加方法和屬性,都是私有的。擴(kuò)展只能在自身類中使用,而不是子類或者其他地方。類擴(kuò)展是在編譯階段添加到類中,而分類是在運行時添加到類中

關(guān)聯(lián)對象

在OC中,關(guān)聯(lián)對象是一種動態(tài)給對象添加屬性的機(jī)制。 正如我們知道的,OC的類可以有實例變量和屬性,這些都是在編譯時期就已經(jīng)確定的。然而,有時候我們可能希望在運行時給對象動態(tài)添加一些屬性,就可以用關(guān)聯(lián)對象。 關(guān)聯(lián)對象還可以為分類添加屬性: Category(分類)的底層結(jié)構(gòu)中,沒有成員變量(ivar),因此不能給分類添加成員變量;在分類里面聲明的屬性,只會生成 get/set 方法的聲明,沒有方法的實現(xiàn),所以我們不能直接給分類添加成員變量,但是可以間接實現(xiàn),那就是使用關(guān)聯(lián)對象

關(guān)聯(lián)對象實際上是通過Objective-C的運行時系統(tǒng)實現(xiàn)的。使用以下三個函數(shù)來添加、獲取或者刪除關(guān)聯(lián)對象:

給對象添加關(guān)聯(lián)對象:

void objc_setAssociatedObject(id object, const void * key, id value, objc_AssociationPolicy policy)

其中objc_AssociationPolicy policy 是指關(guān)聯(lián)策略。 獲取對象的關(guān)聯(lián)對象:

id objc_getAssociatedObject(id object, const void * key)

刪除對象的所有關(guān)聯(lián)對象:

void objc_removeAssociatedObjects(id object)

使用方法:

創(chuàng)建ZSXPerson類,以及它的分類ZSXPerson+TextZSXPerson+Text.h中聲明想要添加的屬性ZSXPerson+Text.m中使用關(guān)聯(lián)對象API實現(xiàn) get/set 方法

修飾符

關(guān)聯(lián)對象并不會改變對象的類或類的定義,它們只是在運行時環(huán)境中與特定的對象關(guān)聯(lián)在一起。關(guān)聯(lián)對象的生命周期與對象本身的生命周期相同,當(dāng)對象被銷毀時,其關(guān)聯(lián)的對象也會被銷毀。

為分類添加關(guān)聯(lián)對象的本質(zhì)

關(guān)聯(lián)對象的本質(zhì)

每一個對象的關(guān)聯(lián)對象實際上都存儲在AssociationHashMap內(nèi)。所有對象的關(guān)聯(lián)內(nèi)容都在同一個全局容器中。 關(guān)聯(lián)對象由AssociationManager管理并在AssociationHashMap存儲。 所以說, 假如給分類添加了一個關(guān)聯(lián)對象, 那么該關(guān)聯(lián)內(nèi)容既不需要分類管理, 也不是由原類管理。

class AssociationsManager {

static spinlock_t _lock;

static AssociationsHashMap *_map; // associative references: object pointer -> PtrPtrHashMap.

public:

AssociationsManager() { _lock.lock(); }

~AssociationsManager() { _lock.unlock(); }

AssociationsHashMap &associations() {

if (_map == NULL)

_map = new AssociationsHashMap();

return *_map;

}

};

AssociationsHashMap內(nèi)部維護(hù)了一個ObjectAssociationMap哈希表:

class AssociationsHashMap : public unordered_map {

public:

void *operator new(size_t n) { return ::malloc(n); }

void operator delete(void *ptr) { ::free(ptr); }

};

ObjectAssociationMap內(nèi)部維護(hù)了一個ObjcAssociation哈希表:

class ObjectAssociationMap : public std::map {

public:

void *operator new(size_t n) { return ::malloc(n); }

void operator delete(void *ptr) { ::free(ptr); }

};

key的常見用法

使用的get方法的@selecor作為key

objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)objc_getAssociatedObject(obj, @selector(getter))

使用指針的地址作為key

static void *MyKey = &MyKey;

objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)objc_getAssociatedObject(obj, MyKey)

使用static字符作為key

static char MyKey;

objc_setAssociatedObject(obj, &MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)objc_getAssociatedObject(obj, &MyKey)

使用屬性名作為key

objc_setAssociatedObject(obj, @“property”, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);objc_getAssociatedObject(obj, @“property”);

錯誤用法舉例

static void *MyKey;

objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)objc_getAssociatedObject(obj, MyKey) 如上寫法,沒有給*MyKey,他相當(dāng)于是NULL,這時候,如果再有另一個屬性使用Keystatic void *OtherKey;,MyKey和OtherKey都是 NULL,這就相當(dāng)于把多個屬性都與NULLKey關(guān)聯(lián),明顯就出問題了

關(guān)聯(lián)對象的實現(xiàn)原理

學(xué)習(xí)OC對象本質(zhì)時,我們知道對象實際被轉(zhuǎn)化成struct ClassName_IMPL結(jié)構(gòu)體,對象的成員變量的值保存在該結(jié)構(gòu)體中。 使用關(guān)聯(lián)對象給分類添加的成員變量,他并不是保存在該結(jié)構(gòu)體下,因為Category的底層結(jié)構(gòu)中并沒有ivar。 他是存儲在全局的統(tǒng)一的一個AssociationsManager中。

核心對象

AssociationsManagerAssociationsHashMapObjectAssociationMapObjcAssociation

下面來看它們之間的關(guān)系:

AssociationsManager

AssociationsManager 是管理所有關(guān)聯(lián)對象的中心管理器。它負(fù)責(zé)存儲和檢索關(guān)聯(lián)對象的整體結(jié)構(gòu)。它是一個單例,確保在整個運行時環(huán)境中只有一個實例。

職責(zé):管理和維護(hù)所有對象的關(guān)聯(lián)數(shù)據(jù)。

AssociationsHashMap

AssociationsHashMap 是一個哈希表,用于將對象映射到它們的關(guān)聯(lián)數(shù)據(jù)。它在內(nèi)部使用了一個哈希表,這個字段的 key 是被添加關(guān)聯(lián)對象的對象的地址,value 是個ObjectAssociationMap

職責(zé):高效地查找和存儲對象與其關(guān)聯(lián)數(shù)據(jù)之間的映射。

ObjectAssociationMap

ObjectAssociationMap 是一個結(jié)構(gòu)體或類,用于存儲單個對象的所有關(guān)聯(lián)數(shù)據(jù)。key 是我們調(diào)用objc_setAssociatedObject時傳入的 key,value 是ObjectAssociation

職責(zé):管理一個對象的所有關(guān)聯(lián)鍵及其對應(yīng)的關(guān)聯(lián)值。

ObjcAssociation

ObjcAssociation 是具體的關(guān)聯(lián)對象,包含實際的數(shù)據(jù)以及數(shù)據(jù)的存儲策略,_policy是我們設(shè)置的修飾符(比如:OBJC_ASSOCIATION_ASSIGN),_value是我們傳入的值value 等。

職責(zé):存儲實際的關(guān)聯(lián)數(shù)據(jù)以及定義數(shù)據(jù)的內(nèi)存管理語義。

工作流程

設(shè)置關(guān)聯(lián)對象:

調(diào)用 objc_setAssociatedObject。AssociationsManager 查找或創(chuàng)建與目標(biāo)對象相關(guān)的 ObjectAssociationMap。在 ObjectAssociationMap 中查找或創(chuàng)建對應(yīng)的 ObjcAssociation。將關(guān)聯(lián)值和存儲策略設(shè)置到 ObjcAssociation 中。 獲取關(guān)聯(lián)對象:

調(diào)用 objc_getAssociatedObject。AssociationsManager 查找與目標(biāo)對象相關(guān)的 ObjectAssociationMap。在 ObjectAssociationMap 中查找對應(yīng)的 ObjcAssociation。返回 ObjcAssociation 中存儲的關(guān)聯(lián)值。 移除關(guān)聯(lián)對象:

調(diào)用 objc_removeAssociatedObjects 或 objc_setAssociatedObject 設(shè)置為 nil。AssociationsManager 查找與目標(biāo)對象相關(guān)的 ObjectAssociationMap。從 ObjectAssociationMap 中移除對應(yīng)的 ObjcAssociation。如果 ObjectAssociationMap 為空,可能會移除整個映射以釋放資源。

objc_AssociationPolicy的值并沒有weak,這點我們在使用的時候需要注意

柚子快報激活碼778899分享:iOS——分類、擴(kuò)展和關(guān)聯(lián)對象

http://yzkb.51969.com/

精彩文章

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19157881.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄