一棒厘、相似
1.都可以修飾對象類型檩互,但是assign修飾對象會存在問題。
2.都是弱引用類蓖柔,不能保住 OC 對象的生命辰企。
二、區(qū)別
1.修飾變量類型的區(qū)別
weak 只可以修飾對象况鸣。如果修飾基本數(shù)據(jù)類型牢贸,編譯器會報錯-“Property with ‘weak’ attribute must be of object type”。
assign 可修飾對象和基本數(shù)據(jù)類型镐捧。
2.是否產(chǎn)生野指針
weak?指向的對象銷毀時潜索,會將當(dāng)前指向?qū)ο蟮闹羔樦赶騨il,防止野指針的生成懂酱。
assign?指向的對象銷毀時竹习,不會將當(dāng)前指向?qū)ο蟮闹羔樦赶騨il,有野指針的生成列牺。
生成用 assign整陌、weak、strong 修飾的三個變量:assignPoint瞎领、weakPonit泌辫、strongPoint;
將 self.strongPoint 賦值給 self.weakPoint 和 self.assignPoint ,然后釋放 self.strongPoint ,那么相應(yīng)的 self.weakPoint 指向的對象就會釋放九默,self.weakPoint 也會將值設(shè)置為nil震放。
而 self.assignPoint 中的引用雖然釋放了,但是值卻還是原來 self.strongPoint 中的值荤西,所以當(dāng)引用的時候就會造成野指針澜搅。
Runtime 如何實現(xiàn) weak 變量的自動置nil伍俘?
Runtime 對注冊的類, 會進(jìn)行布局勉躺,對于 weak 對象會放入一個 hash 表中癌瘾。 用 weak 指向的對象內(nèi)存地址作為 key,當(dāng)此對象的引用計數(shù)為0的時候會 dealloc饵溅,假如 weak 指向的對象內(nèi)存地址是a妨退,那么就會以a為鍵, 在這個 weak 表中搜索蜕企,找到所有以a為鍵的 weak 對象咬荷,從而設(shè)置為 nil。
Runtime 如何實現(xiàn) weak 屬性具體流程大致分為 3 步:
1轻掩、初始化時:runtime 會調(diào)用 objc_initWeak 函數(shù)幸乒,初始化一個新的 weak 指針指向?qū)ο蟮牡刂贰?/p>
2、添加引用時:objc_initWeak 函數(shù)會調(diào)用 objc_storeWeak() 函數(shù)唇牧,objc_storeWeak() 的作用是更新指針指向(指針可能原來指向著其他對象罕扎,這時候需要將該 weak 指針與舊對象解除綁定,會調(diào)用到 weak_unregister_no_lock)丐重,如果指針指向的新對象非空腔召,則創(chuàng)建對應(yīng)的弱引用表,將 weak 指針與新對象進(jìn)行綁定扮惦,會調(diào)用到 weak_register_no_lock臀蛛。在這個過程中,為了防止多線程中競爭沖突崖蜜,會有一些鎖的操作浊仆。
3、釋放時:調(diào)用 clearDeallocating 函數(shù)豫领,clearDeallocating 函數(shù)首先根據(jù)對象地址獲取所有 weak 指針地址的數(shù)組氧卧,然后遍歷這個數(shù)組把其中的數(shù)據(jù)設(shè)為 nil,最后把這個 entry 從 weak 表中刪除氏堤,最后清理對象的記錄。