了解hash的重要性
在iOS開發(fā)中 隨處可見hash的身影,hash對(duì)于iOS開發(fā)起到了支撐的作用。
下圖是部分具體應(yīng)用之處,圖片較為模糊,下面會(huì)每一個(gè)點(diǎn)的去介紹,分析其中的原理。

對(duì)于iOS 開發(fā)人員來講,雖然我們處于應(yīng)用層的開發(fā)。所使用的技術(shù)已經(jīng)是高度封裝的API.對(duì)于我們來說,純調(diào)用接口交互,和用戶交互成為了移動(dòng)端開發(fā)人員主要的工作任務(wù)。對(duì)于算法、數(shù)據(jù)結(jié)構(gòu)、通信協(xié)議、文件系統(tǒng)、驅(qū)動(dòng)等。雖然工作中沒有人會(huì)過多的去質(zhì)問這個(gè)程序的底層實(shí)現(xiàn)方案。俗話說的好,學(xué)而不思則罔,思而不學(xué)則怠。凡事知其然必要知其所以然。才能更好的運(yùn)用所掌握 的技能。從而游刃有余,而事半功倍。話不多說,下面詳細(xì)介紹下hash中具體的使用。
1.1、關(guān)聯(lián)對(duì)象的實(shí)現(xiàn)原理:
關(guān)聯(lián)對(duì)象是什么?關(guān)聯(lián)對(duì)象說起來,還的追溯到runtime底層的C代碼和匯編代碼。
是利用運(yùn)行時(shí)機(jī)制.給對(duì)象動(dòng)態(tài)增添屬性成員變量的機(jī)制。術(shù)語就是AssocateObject .采用的便是hash表進(jìn)行的數(shù)據(jù)處理。是利用的hash表嵌套hash表的數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)。
簡(jiǎn)單來說就是根據(jù)對(duì)象從從第一個(gè)HashMap中取出存儲(chǔ)對(duì)象所有關(guān)聯(lián)對(duì)象的第二個(gè)HashMap,然后根據(jù)屬性名從第二個(gè)HashMap中取出屬性對(duì)應(yīng)的值和策略。
設(shè)計(jì)關(guān)聯(lián)對(duì)象的初衷是,通過傳入對(duì)象+屬性名字,就可以找到屬性值。方案設(shè)計(jì)好后,查找一個(gè)對(duì)象的關(guān)聯(lián)對(duì)象的基本步驟:
1.已知條件一:對(duì)象,因此引出第一個(gè)HashMap,用一個(gè)能唯一代表對(duì)象的值作為key,用存儲(chǔ)對(duì)象的所有關(guān)聯(lián)對(duì)象的結(jié)構(gòu)(值+策略)作為value.
2.已知條件二:屬性名字,因此引出第二個(gè)HashMap,用屬性名字作為key.用屬性名字對(duì)應(yīng)的結(jié)構(gòu)(值+策略)作為value.
1.2、weak實(shí)現(xiàn)原理:
weak采用的是一個(gè)全局的HashMap嵌套數(shù)組的結(jié)構(gòu)存儲(chǔ)數(shù)據(jù)的。銷毀對(duì)象(weak指針指向的對(duì)象)的時(shí)候,根據(jù)對(duì)象從HashMap中找到存放所有指向該對(duì)象的weak指針的數(shù)組,然后將數(shù)組中的所有元素(weak指針)都置為nil.
weak最大特點(diǎn)就是在銷毀對(duì)象的時(shí)候,自動(dòng)置為nil,減少訪問野指針的風(fēng)險(xiǎn)。這也是設(shè)計(jì)weak的初衷。方案設(shè)計(jì)實(shí)現(xiàn)好后,weak指針置nil的基本步驟:
-1、對(duì)象dealloc的時(shí)候,從全局的HashMap中,根據(jù)一個(gè)唯代表對(duì)象的值作為 key,找到存儲(chǔ)所有志向該對(duì)象的weak指針數(shù)組。
-2、將數(shù)組中的所有元素都置為nil
蘋果對(duì)于weak的實(shí)現(xiàn)其實(shí)類似于通知的實(shí)現(xiàn),指明誰(weak指針)要監(jiān)聽誰(賦值對(duì)象)什么事件(dealloc操作)執(zhí)行什么操作(置nil).
1.3、KVO實(shí)現(xiàn)使用的基本數(shù)據(jù)結(jié)構(gòu)
比較復(fù)雜,一個(gè)對(duì)象可以被n個(gè)對(duì)象觀察,一個(gè)對(duì)象的n個(gè)屬性又可以被n個(gè)對(duì)像觀察。
1.4、iOS App簽名的原理
通俗來說就是: 一致性哈希算法 + 非對(duì)稱加解密算法。
1.5、對(duì)象引用計(jì)數(shù)的存儲(chǔ)位置
if 對(duì)象支持TaggedPointer {
return 直接將對(duì)象的指針值作為引用計(jì)數(shù)返回
}
else if 設(shè)備是64位環(huán)境 && Objective-C2.0 {
return 對(duì)象isa指針的一部分空間(bits_extra_rc)
}
else {
return hash表
}
1.6、Runloop與線程的存儲(chǔ)關(guān)系
線程和Runloop之間是--(子線程可以沒有)對(duì)應(yīng)的,其關(guān)系是保存在一個(gè)全局的dictionary里。線程創(chuàng)建時(shí)并沒有Runloop,如果你不主動(dòng)獲取,那么就一直沒有。Runloop的創(chuàng)建是發(fā)生在第一次獲取時(shí),Runloop的銷毀是發(fā)生在線程結(jié)束時(shí)。你只能在一個(gè)線程的內(nèi)部獲取其 Runloop(主線程外)。
1.7、NSDictionary的原理:
這里說到NSDictionary的原理,就要先大體了解介紹下hashMap的原理。
hashMap通過 拉鏈法和開放定址線性探測(cè)發(fā) 來解決哈希沖突。這里Apple都是用了的。具體使用哪一種解決方法是要根據(jù)存儲(chǔ)數(shù)據(jù)的生命周期和特性決定的。
-@synchronized使用的是拉鏈法。拉鏈法多用于存儲(chǔ)解決的數(shù)據(jù)是通用類型,能夠被反復(fù)利用,就像@synchronized存儲(chǔ)的是鎖是一種無業(yè)務(wù)的實(shí)現(xiàn)結(jié)構(gòu),程序運(yùn)行多個(gè)對(duì)象使用同一個(gè)鎖的概率相當(dāng)高,有效的節(jié)省了內(nèi)存。
-weak對(duì)象associateObject采用的是開發(fā)定址性探測(cè)法。開放定址探測(cè)法用于存儲(chǔ)的數(shù)據(jù)是臨時(shí)的,用完盡量釋放,就像associateObject,weak.
NSDictionary的存儲(chǔ)過程:
1、通過方法 - (void)setObject:(id)anObject forKey:(id)key;可以看出key必須遵守NScopy協(xié)議,也即是說NSDictionary的key是copy一份新的,而value是淺拷貝的。
2、不過這還不夠,key還必須要繼承NSObject,并且重寫-(NSUInteger)hash和-(Bool)isequal:(id )object兩個(gè)方法。第一個(gè)函數(shù)用于計(jì)算hash值,第二個(gè)函數(shù)用于判斷當(dāng)哈希值相同的時(shí)候value是否相同(解決hash沖突)。