一圆丹、 內(nèi)存管理
1 管理方式:MRC(已經(jīng)很少用) ARC(常用)
ARC:稱為自動(dòng)引用計(jì)數(shù)墓捻,ARC是iOS5推出的功能谜叹,通過(guò)ARC系統(tǒng)可以自動(dòng)管理內(nèi)存右锨。在ARC下只要所有的強(qiáng)引用(指針)引用對(duì)象括堤,那么該對(duì)象就會(huì)被釋放。
注意: ARC下不允許使用retain绍移、release悄窃、retainCount等MRC下使用的方法,如果使用dealloc方法時(shí)不允許調(diào)用[super dealloc]
二蹂窖、與內(nèi)存相關(guān)的修飾符
- strong:強(qiáng)引用轧抗,使用后該對(duì)象的‘計(jì)數(shù)器’+1。
- weak: 弱引用瞬测,使用后該對(duì)象的‘計(jì)數(shù)器’引用計(jì)數(shù)為1横媚,當(dāng)沒(méi)有其他強(qiáng)指針引用該修飾符修飾的對(duì)象后,該對(duì)象被置為nil月趟,weak可以有效的避免野指針灯蝴。
- readwrite: 可讀可寫修飾符,需要生成setter和getter時(shí)使用孝宗,一般省略穷躁。
- readonly: 只讀,只會(huì)生成getter不會(huì)生成setter因妇,如果對(duì)該修飾符修飾的對(duì)象賦值會(huì)報(bào)錯(cuò)问潭。
- assign: 賦值特性,不涉及引用計(jì)數(shù)沙峻,弱引用睦授。setter方法講傳入?yún)?shù)賦值給實(shí)例變量。
- retain:表示持有特性摔寨,setter方法將傳入?yún)?shù)先保留去枷,再賦值,‘計(jì)數(shù)器’+1
- copy:表示拷貝特性,setter方法傳入的對(duì)象會(huì)被復(fù)制一份删顶,需要生成新的對(duì)象時(shí)使用竖螃。一般用于字符串、NSMultebleArray等逗余。
- nonatomic: 非原子操作特咆,不加同步,非線程安全录粱。對(duì)線程訪問(wèn)時(shí)可以提高性能腻格。決定編譯器生成setter和getter是否是原子操作。
- atomic: 原子操作啥繁,同步的菜职,線程安全,與nonatomic相反
- weak vs assign
weak:在ARC中旗闽,在有可能出現(xiàn)循環(huán)引用的時(shí)候酬核,往往通過(guò)讓其中一端將強(qiáng)引用變?yōu)槿跻脕?lái)解決問(wèn)題,防止多次強(qiáng)引用時(shí)也需要用到weak适室。
weak是表示該屬性定義了一種‘非擁有關(guān)系’嫡意。這種屬性設(shè)置新值時(shí),設(shè)置方法既不保留新值也不釋放舊值捣辆。當(dāng)屬性值所指向的對(duì)象遭到銷毀時(shí)蔬螟,屬性值也會(huì)清空。assing的‘設(shè)置方法’只會(huì)用于‘純量類型’的簡(jiǎn)單賦值操作(例如CGFloat罪帖、NSInteger等)
assign可以用于非OC對(duì)象促煮,而weak必須用于OC對(duì)象
三、Autorelease
autorelease是一種支持引用計(jì)數(shù)的內(nèi)存管理方式整袁,autorelease實(shí)際上只是把對(duì)release的調(diào)用延遲了。對(duì)于每個(gè)autorelease佑吝,系統(tǒng)只是把該對(duì)象放入了當(dāng)前的autorelease pool中坐昙,當(dāng)該pool釋放時(shí),該pool中的所有對(duì)象會(huì)被調(diào)用release
- autorelease何時(shí)釋放: 1芋忿,手動(dòng)釋放 2炸客,runloop結(jié)束后自動(dòng)釋放
- 原理:程序在main()調(diào)用的時(shí)候會(huì)自動(dòng)創(chuàng)建一個(gè)autorelease,然后在每一個(gè)runloop戈钢,系統(tǒng)會(huì)隱式創(chuàng)建一個(gè)autorelease pool痹仙,這樣所有的release pool會(huì)構(gòu)成一個(gè)棧式結(jié)構(gòu),每一個(gè)runloop結(jié)束時(shí)殉了,當(dāng)前棧頂?shù)腶utorelease pool會(huì)被銷毀开仰,這樣pool里的每個(gè)對(duì)象都會(huì)被release
注意: ARC下之能使用@ autoreleasepool block乃沙,盡量避免對(duì)大內(nèi)存使用該方法。不要把大量的循環(huán)操作放到統(tǒng)一個(gè)autorelease pool中蛤肌,這樣會(huì)造成內(nèi)存峰值乓序。
問(wèn)題:autorelease pool 什么時(shí)候釋放
- 在沒(méi)有手動(dòng)加autorelease pool的情況下,autorelease對(duì)象是在當(dāng)前的runloop迭代結(jié)束時(shí)釋放的谓娃,它能夠釋放的原因是系統(tǒng)在每個(gè)runloop迭代中都加入了autoreleasepool push和pop
四脚乡、內(nèi)存泄露(memory leak)
- oc與c混編,c使用的內(nèi)存沒(méi)有被釋放
- block或者其他原因?qū)е卵h(huán)引用會(huì)產(chǎn)生內(nèi)存泄露
- NSTimer對(duì)象會(huì)對(duì)它的target進(jìn)行retain滨达,從而保證了timer調(diào)用時(shí)的正確性奶稠,但是又會(huì)引入了接收者的內(nèi)存管理問(wèn)題,特別是對(duì)于重復(fù)性的timer捡遍,他所引用的對(duì)象一直存在窒典,這將會(huì)導(dǎo)致內(nèi)存泄露。解決的辦法是稽莉,NSTimer提供了一個(gè)invalidate的方法瀑志,在執(zhí)行完invalidate方法后timer會(huì)變無(wú)效。
五污秆、循環(huán)引用
- block在執(zhí)行copy時(shí)會(huì)對(duì)block內(nèi)部用到的對(duì)象進(jìn)行強(qiáng)引用劈猪,當(dāng)某個(gè)類將block作為自己的全局變量強(qiáng)引用,然后該類在block里有使用了該類本身良拼,它們之間會(huì)形成一個(gè)強(qiáng)引用環(huán)战得,都無(wú)法釋放,就會(huì)導(dǎo)致循環(huán)引用庸推。
- 解決辦法:
__weak typeof(self) weakSelf=self;
在block里使用weakSelf - 在使用代理模式的時(shí)候要注意Delegate一定是weak的常侦,否則會(huì)導(dǎo)致代理和原對(duì)象之間形成強(qiáng)引用循環(huán)導(dǎo)致循環(huán)引用。
- 解決辦法:
六贬媒、OC對(duì)象與CF對(duì)象的橋接
- __bridge只做OC和CF對(duì)象之間的類型轉(zhuǎn)換不涉及對(duì)象的所有權(quán)的轉(zhuǎn)化
- __bridge_transfer:用在將CF對(duì)象轉(zhuǎn)換成OC對(duì)象時(shí)聋亡,并且將CF對(duì)象的所有權(quán)交給OC對(duì)象,此時(shí)ARC就能自動(dòng)管理內(nèi)存了际乘。作用同于CFBridgeTranfer()
- __bridge_retainde:用在將OC對(duì)象轉(zhuǎn)換成CF對(duì)象坡倔,并且將OC對(duì)象的所有權(quán)交給CF對(duì)象來(lái)管理,作用同于CFBridgeRetain()。此時(shí)我們要使用完CF對(duì)象后用CFRelease將其手動(dòng)釋放脖含。
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
CFURLRef urlRef = (__bridge_retained CFURLRef)url;
CFRelease(urlRef);