說到iOS的內(nèi)存管理,需要明白如下幾個問題:
1变隔、iOS內(nèi)存管理的機(jī)制
內(nèi)存管理是程序設(shè)計(jì)中很重要的一部分规伐,程序在運(yùn)行的過程中消耗內(nèi)存,運(yùn)行結(jié)束后釋放占用的內(nèi)存匣缘。如果程序運(yùn)行時一直分配內(nèi)存而不及時釋放無用的內(nèi)存猖闪,會造成這樣的后果:程序占用的內(nèi)存越來越大,直至內(nèi)存消耗殫盡肌厨,程序因無內(nèi)存可用導(dǎo)致崩潰培慌,這樣的情況我們稱之為內(nèi)存泄漏。
2柑爸、在哪開辟內(nèi)存吵护?什么時候開辟內(nèi)存?什么時候釋放內(nèi)存表鳍?
IOS開發(fā)中馅而,內(nèi)存中的對象主要有兩類,一類是值類型譬圣,比如int瓮恭、float、struct等基本數(shù)據(jù)類型厘熟,另一類是引用類型屯蹦,也就是繼承自NSObject類的所有的OC對象。前一種值類型不需要我們管理绳姨,后一種引用類型是需要我們管理內(nèi)存的登澜,一旦管理不好,就會產(chǎn)生非常糟糕的后果飘庄。
為什么值類型不需要管理內(nèi)存脑蠕,而引用類型需要?
因?yàn)橹殿愋褪谴鎯Φ綏V械慕咴祝麄兿冗M(jìn)先出空郊,依次緊密排列份招;引用類型是存儲在堆上的切揭,給對象開辟空間時會隨機(jī)從內(nèi)存開辟空間。
棧內(nèi)存與堆內(nèi)存從性能上比較锁摔,棧內(nèi)存要優(yōu)于堆內(nèi)存廓旬,這是因?yàn)闂W裱冗M(jìn)后出的原則,因此當(dāng)數(shù)據(jù)量過大時,存入棧會明顯的降低性能孕豹。因此涩盾,我們會把大量的數(shù)據(jù)存入堆中,然后棧中存放堆的地址励背,當(dāng)需要調(diào)用數(shù)據(jù)時春霍,就可以快速的通過棧內(nèi)的地址找到堆中的數(shù)據(jù)。
值類型和引用類型之間是可以相互轉(zhuǎn)化的叶眉,把值類型轉(zhuǎn)化為引用類型的過程叫做裝箱址儒,比如把int包裝為NSNumber,這個過程會增加程序的運(yùn)行時間衅疙,降低性能莲趣。而把引用類型轉(zhuǎn)為值類型的過程叫做拆箱,比如把NSNumer轉(zhuǎn)為float饱溢,在拆箱的過程中喧伞,我們一定要注意數(shù)據(jù)原有的類型,如果類型錯誤绩郎,可能導(dǎo)致拆箱失敗潘鲫,因此會存在安全性的問題。手動的拆箱和裝箱嗽上,都會增加程序的運(yùn)行時間次舌,降低代碼可讀性,影響性能兽愤。
在IOS開發(fā)過程中彼念,棧內(nèi)存中的值類型系統(tǒng)會自動管理,堆內(nèi)存中的引用類型是需要我們管理的浅萧。每個OC對象內(nèi)部都專門有四個字節(jié)來存儲引用計(jì)數(shù)器逐沙,它是一個整數(shù),表示對象被引用的次數(shù)洼畅,通過它可以判斷對象是否被回收吩案,如果引用計(jì)數(shù)為0,對象回收帝簇,不為0不回收徘郭。當(dāng)對象執(zhí)行alloc、new或者retain時丧肴,引用計(jì)數(shù)加1残揉,release時,引用計(jì)數(shù)減1芋浮。
3抱环、幾個關(guān)鍵字
MRC手動管理模式
MRC遵循誰開辟內(nèi)存,誰釋放內(nèi)存的原則。誰alloc镇草,誰release眶痰;誰retain,誰relase梯啤。引用計(jì)數(shù)為0的時候收回竖伯,如果為0時,沒有被收回因宇,則會出現(xiàn)內(nèi)存泄漏黔夭。
ARC自動管理模式
ARC內(nèi)存管理增加了strong和weak關(guān)鍵字,相當(dāng)于MRC的retain和assign羽嫡,不過weak可以釋放指針對象本姥,指針指向的地址被釋放后本身也會被釋放。
strong :強(qiáng)引用杭棵,ARC中使用婚惫,與MRC中retain類似,使用之后魂爪,計(jì)數(shù)器+1先舷。
weak :弱引用 ,ARC中使用滓侍,如果只想的對象被釋放了蒋川,其指向nil,可以有效的避免野指針撩笆,其引用計(jì)數(shù)為1捺球。在MRC中,如果引用計(jì)數(shù)為0夕冲,繼續(xù)release就會造成野指針
readwrite : 可讀可寫特性氮兵,需要生成getter方法和setter方法時使用。
readonly : 只讀特性歹鱼,只會生成getter方法 不會生成setter方法泣栈,不希望屬性在類外改變。
assign :賦值特性弥姻,不涉及引用計(jì)數(shù)南片,弱引用,setter方法將傳入?yún)?shù)賦值給實(shí)例變量庭敦,僅設(shè)置變量時使用疼进。
retain :表示持有特性,setter方法將傳入?yún)?shù)先保留螺捐,再賦值颠悬,傳入?yún)?shù)的retaincount會+1。
copy :表示拷貝特性定血,setter方法將傳入對象復(fù)制一份赔癌,需要完全一份新的變量時。
nonatomic :非原子操作澜沟,不加同步灾票,多線程訪問可提高性能,但是線程不安全的茫虽。決定編譯器生成的setter getter是否是原子操作刊苍。
atomic :原子操作,同步的濒析,表示多線程安全正什,與nonatomic相反。
4号杏、深拷貝和淺拷貝婴氮,有什么影響?不同類型的限制
淺拷貝是將原始對象中的數(shù)據(jù)型字段拷貝到新對象中去盾致,將引用型字段的“引用”復(fù)制到新對象中去主经,不把“引用的對象”復(fù)制進(jìn)去,所以原始對象和新對象引用同一對象庭惜,新對象中的引用型字段發(fā)生變化會導(dǎo)致原始對象中的對應(yīng)字段也發(fā)生變化罩驻。
? ? 深拷貝是在引用方面不同,深拷貝就是創(chuàng)建一個新的和原始字段的內(nèi)容相同的字段护赊,是兩個一樣大的數(shù)據(jù)段惠遏,所以兩者的引用是不同的,之后的新對象中的引用型字段發(fā)生改變骏啰,不會引起原始對象中的字段發(fā)生改變爽哎。
我們可以認(rèn)為,如果對一不可變對象復(fù)制器一,copy是指針復(fù)制(淺拷貝)和mutableCopy就是對象復(fù)制(深拷貝)课锌。如果是對可變對象復(fù)制,都是深拷貝祈秕,但是copy返回的對象是不可變的渺贤。mutableCopy總會產(chǎn)生新對象,實(shí)現(xiàn)深拷貝请毛。注意看第五點(diǎn)志鞍,產(chǎn)生的副本對象!