IOS内存管理2
? ??很多童鞋對于IOS中的內(nèi)存管理處理的不好,有時候感覺自己已經(jīng)掌握了,其實(shí)用起來的時候往往出現(xiàn)很多的內(nèi)存泄露或者因為內(nèi)存管理的不恰當(dāng)導(dǎo)致程序崩潰!
網(wǎng)上有一片很詳細(xì)的內(nèi)存管理文章,很多人估計嫌長,不愿意去看,我就寫一個簡單易懂的分享。
我分四塊來講解,這篇文章比較簡單,因為我不想把你們搞暈,其實(shí)總的來說就一個原則!
一、IOS內(nèi)存管理的機(jī)制
IOS中沒有垃圾回收機(jī)制(IOS5中好像已經(jīng)有了,但是目前還不太實(shí)用),所以基本一切都是自己手動管理。
IOS中采用引用計數(shù)的內(nèi)存管理方式,啥意思呢?講的通俗點(diǎn)就是說一塊內(nèi)存地址是否應(yīng)該被釋放是又retaincount來決定的,如果這塊內(nèi)存地址的retaincount為0,那么這塊內(nèi)存就會被釋放,再也找不到了。
所以想讓他一直存在,那么它的retaincount就必須大于0。
那么如何管理呢?其實(shí)原理非常簡單,就是誰用誰retain,誰retain的誰release,遵循這個原則的目的就是讓你不會出錯。
舉個例子 ? ClassA *obj1 = [[ClassA alloc] init];?
這里你申請了一塊內(nèi)存地址,指針obj1指向了這塊內(nèi)存地址,同時你給它retain了一下(retain,copy,alloc這幾個方法都相當(dāng)于把retaincount加一),此時obj1所指向的這塊內(nèi)存地址retaincount為1。
接著來(這里我只是舉例子讓大家了解一下,這些代碼沒有什么實(shí)際意義)
ClassA *obj2=obj1;
[obj2 retain]; ? 好了,大家看一下,obj1和obj2同時都指向了上面所述的內(nèi)存地址,我假設(shè)這塊內(nèi)存為A,那么A這塊內(nèi)存的retaincount為2。
假如大家在之后一直在使用obj1和obj2,最后不用的時候,需要釋放了,我希望大家這樣來釋放
? [obj1 release];
[obj2 release];
? 而不希望大家這樣來釋放
[obj1 release];
[obj1 release];
//或者
[obj2 release];
[obj2 release]; ? 為什么這樣呢?上面兩種釋放方法沒有錯,都成功將A這塊內(nèi)存的retaincount減為0,導(dǎo)致A被釋放了。但是你沒有遵循以上所說“誰用誰retain,誰retain的誰release”。
這只是一個小例子,你可能感覺不到問題的嚴(yán)重性,如果你做一個項目,在其中有大量這種retain,release的話,你不遵循這種原則,你會死的很慘,沒有條理最后你會被搞的很亂,找都找不到。
二、不要隨便看到retaincount多就給它釋放
很多朋友在學(xué)完內(nèi)存管理后喜歡玩消除,不該釋放的他去釋放,舉個例子
? UIViewController *ct1=[[UIViewController alloc] init];[self.navigationcontroller pushViewController:ct1 animated:YES];[ct1 relese];
? 這里,初始化一個viewcontroller,然后用導(dǎo)航push進(jìn)來,最后釋放這個viewcontroller,很多人在這里操作完畢后,繼續(xù)打印ct1的retaincount,發(fā)現(xiàn)它的retaincount不為0,就繼續(xù)release,這里是非常錯誤的方法,直接導(dǎo)致程序崩潰,繼續(xù)看以上原則“誰用誰retain,誰retain的誰release”,你用的時候,初始化,并retain了一次,最后你release了一次,到此結(jié)束!之后不管你發(fā)現(xiàn)它的retaincount為幾,你都不該再release。你打印出來的retaincount并不是你retain的,而是系統(tǒng)框架本身retain的,由框架本身來處理,開發(fā)者不必理會。
類似還有很多,數(shù)組的addobject、addsubview等等很多方法,都是框架自己家retain的,開發(fā)者本身retain后release,不必理會它的retaincount。
另外插一句,如果是多人協(xié)同開發(fā),這種情況最容易碰到,別人傳遞一個參數(shù)過來,你拿過來retain后使用,使用完畢release,發(fā)現(xiàn)retaincount還不是0,于是你繼續(xù)release,這樣你就把你同伴retain的計數(shù)給release掉了,當(dāng)他下次使用的時候發(fā)現(xiàn)崩潰了,這種情況會讓你的團(tuán)隊浪費(fèi)無數(shù)的時間來找原因。
? 三、關(guān)于屬性
屬性在.h文件中是這樣聲明的 ? @property(nonatomic,retain) Class *obj;
? 括號內(nèi)第二個參數(shù)代表的意義是什么呢?
我們分析一下他內(nèi)部的機(jī)制
@property (retain) Class* obj;和@synthesize obj;實(shí)際上是getter和setter,有retain參數(shù)的property,內(nèi)部代碼如下
? -(Class *) getObj
{
? ? ? ? ?return obj;
}
-(void) setObj:(Class *) value
{
? ? ? ? ?if (obj != value)
? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?[obj release];
? ? ? ? ? ? ? ? ? ?obj = [value retain];
? ? ? ? ?}
}
愿意仔細(xì)分析的童鞋可以仔細(xì)研究一下,不太明朗的童鞋請聽我說。
這個屬性定義以后如何使用呢?我們只說賦值(也就是set)
self.obj=xxx;
[self setObj:xxx];
obj=xxx;
賦值方法有以下幾種,其中前兩個是相同的,都是調(diào)用了setObj:方法同時也就導(dǎo)致了obj的retaincount增加了1,而第三個賦值方法并沒有增加retaincount,只是將指針指向了xxx內(nèi)存地址。
所以大家賦值時可以這樣
Class *c=[[Class alloc] init]; self.obj=c;[c release];
或者Class *c=[[Class alloc] init]; [self setObj:c];[c release]; 或者Class *c=[[Class alloc] init];obj=c;
? 屬性的這個機(jī)制是讓你在整個self里(也就是當(dāng)前類的實(shí)例里)一直保留這個obj的retaincount,所以你必須在此類的dealloc里將obj的retaincount置零(你只需要release,如果你嚴(yán)格遵守“誰用誰retain,誰retain的誰release”的話)
-(void)dealloc
{
? ? [obj release];
? ? [super dealloc];
} ? ? 這里,其實(shí)我主要要說明的就是屬性的賦值方式用self.xxx=xxxx和xxx=xxxx是完全不同的賦值方式,大家切記!
四、autorelease對象
autorelease對象就是自動釋放對象,大家可能會疑惑,能自動釋放,我還管理干嘛,我都用自動釋放算了,事實(shí)不是這樣的,自動釋放確實(shí)好用,但是自己管理內(nèi)存才能讓項目占用更小的資源,跑起來更流暢,大家可以手動管理加autorelease一起來使用,我先講解一下autorelease對象到底是什么個情況。
首先,告訴大家autorelease對象什么時候才會被釋放。
在main函數(shù)里有一個autorelease pool,自動釋放池,所以在這個自動釋放池里的autorelease對象都會在自動釋放池結(jié)束的時候全部被釋放。
大家可能會問了,“難道所有的autorelease對象都是在程序退出的時候才被釋放?”,答案當(dāng)然不是,其實(shí)main函數(shù)中只是一個程序中眾多自動釋放池中的一個,每個runloop都會隱性的創(chuàng)建一個自動釋放池,啥是一個runloop?每個UIView創(chuàng)建、delegate回調(diào)等等都會創(chuàng)建一個自動釋放池,記得這個“等等”,意思就是有很多(如果大家想要詳細(xì)了解runloop,可以去google)。所以大家不用擔(dān)心autorelease對象不會被釋放。
很多系統(tǒng)的方法,比如[NSArray array]、[NSString stringformat]等等返回的對象都是autorelease對象,這些對象是不需要手動釋放的,如果手動釋放會導(dǎo)致程序崩潰!切記!,原則就是系統(tǒng)中所有沒有使用alloc、copy、retain來創(chuàng)建的對象都是autorelease對象,大家千萬別手動release!
轉(zhuǎn):http://blog.csdn.net/tt5267621/article/details/7632004
網(wǎng)上有一片很詳細(xì)的內(nèi)存管理文章,很多人估計嫌長,不愿意去看,我就寫一個簡單易懂的分享。
我分四塊來講解,這篇文章比較簡單,因為我不想把你們搞暈,其實(shí)總的來說就一個原則!
一、IOS內(nèi)存管理的機(jī)制
IOS中沒有垃圾回收機(jī)制(IOS5中好像已經(jīng)有了,但是目前還不太實(shí)用),所以基本一切都是自己手動管理。
IOS中采用引用計數(shù)的內(nèi)存管理方式,啥意思呢?講的通俗點(diǎn)就是說一塊內(nèi)存地址是否應(yīng)該被釋放是又retaincount來決定的,如果這塊內(nèi)存地址的retaincount為0,那么這塊內(nèi)存就會被釋放,再也找不到了。
所以想讓他一直存在,那么它的retaincount就必須大于0。
那么如何管理呢?其實(shí)原理非常簡單,就是誰用誰retain,誰retain的誰release,遵循這個原則的目的就是讓你不會出錯。
舉個例子 ? ClassA *obj1 = [[ClassA alloc] init];?
這里你申請了一塊內(nèi)存地址,指針obj1指向了這塊內(nèi)存地址,同時你給它retain了一下(retain,copy,alloc這幾個方法都相當(dāng)于把retaincount加一),此時obj1所指向的這塊內(nèi)存地址retaincount為1。
接著來(這里我只是舉例子讓大家了解一下,這些代碼沒有什么實(shí)際意義)
ClassA *obj2=obj1;
[obj2 retain]; ? 好了,大家看一下,obj1和obj2同時都指向了上面所述的內(nèi)存地址,我假設(shè)這塊內(nèi)存為A,那么A這塊內(nèi)存的retaincount為2。
假如大家在之后一直在使用obj1和obj2,最后不用的時候,需要釋放了,我希望大家這樣來釋放
? [obj1 release];
[obj2 release];
? 而不希望大家這樣來釋放
[obj1 release];
[obj1 release];
//或者
[obj2 release];
[obj2 release]; ? 為什么這樣呢?上面兩種釋放方法沒有錯,都成功將A這塊內(nèi)存的retaincount減為0,導(dǎo)致A被釋放了。但是你沒有遵循以上所說“誰用誰retain,誰retain的誰release”。
這只是一個小例子,你可能感覺不到問題的嚴(yán)重性,如果你做一個項目,在其中有大量這種retain,release的話,你不遵循這種原則,你會死的很慘,沒有條理最后你會被搞的很亂,找都找不到。
二、不要隨便看到retaincount多就給它釋放
很多朋友在學(xué)完內(nèi)存管理后喜歡玩消除,不該釋放的他去釋放,舉個例子
? UIViewController *ct1=[[UIViewController alloc] init];[self.navigationcontroller pushViewController:ct1 animated:YES];[ct1 relese];
? 這里,初始化一個viewcontroller,然后用導(dǎo)航push進(jìn)來,最后釋放這個viewcontroller,很多人在這里操作完畢后,繼續(xù)打印ct1的retaincount,發(fā)現(xiàn)它的retaincount不為0,就繼續(xù)release,這里是非常錯誤的方法,直接導(dǎo)致程序崩潰,繼續(xù)看以上原則“誰用誰retain,誰retain的誰release”,你用的時候,初始化,并retain了一次,最后你release了一次,到此結(jié)束!之后不管你發(fā)現(xiàn)它的retaincount為幾,你都不該再release。你打印出來的retaincount并不是你retain的,而是系統(tǒng)框架本身retain的,由框架本身來處理,開發(fā)者不必理會。
類似還有很多,數(shù)組的addobject、addsubview等等很多方法,都是框架自己家retain的,開發(fā)者本身retain后release,不必理會它的retaincount。
另外插一句,如果是多人協(xié)同開發(fā),這種情況最容易碰到,別人傳遞一個參數(shù)過來,你拿過來retain后使用,使用完畢release,發(fā)現(xiàn)retaincount還不是0,于是你繼續(xù)release,這樣你就把你同伴retain的計數(shù)給release掉了,當(dāng)他下次使用的時候發(fā)現(xiàn)崩潰了,這種情況會讓你的團(tuán)隊浪費(fèi)無數(shù)的時間來找原因。
? 三、關(guān)于屬性
屬性在.h文件中是這樣聲明的 ? @property(nonatomic,retain) Class *obj;
? 括號內(nèi)第二個參數(shù)代表的意義是什么呢?
我們分析一下他內(nèi)部的機(jī)制
@property (retain) Class* obj;和@synthesize obj;實(shí)際上是getter和setter,有retain參數(shù)的property,內(nèi)部代碼如下
? -(Class *) getObj
{
? ? ? ? ?return obj;
}
-(void) setObj:(Class *) value
{
? ? ? ? ?if (obj != value)
? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?[obj release];
? ? ? ? ? ? ? ? ? ?obj = [value retain];
? ? ? ? ?}
}
愿意仔細(xì)分析的童鞋可以仔細(xì)研究一下,不太明朗的童鞋請聽我說。
這個屬性定義以后如何使用呢?我們只說賦值(也就是set)
self.obj=xxx;
[self setObj:xxx];
obj=xxx;
賦值方法有以下幾種,其中前兩個是相同的,都是調(diào)用了setObj:方法同時也就導(dǎo)致了obj的retaincount增加了1,而第三個賦值方法并沒有增加retaincount,只是將指針指向了xxx內(nèi)存地址。
所以大家賦值時可以這樣
Class *c=[[Class alloc] init]; self.obj=c;[c release];
或者Class *c=[[Class alloc] init]; [self setObj:c];[c release]; 或者Class *c=[[Class alloc] init];obj=c;
? 屬性的這個機(jī)制是讓你在整個self里(也就是當(dāng)前類的實(shí)例里)一直保留這個obj的retaincount,所以你必須在此類的dealloc里將obj的retaincount置零(你只需要release,如果你嚴(yán)格遵守“誰用誰retain,誰retain的誰release”的話)
-(void)dealloc
{
? ? [obj release];
? ? [super dealloc];
} ? ? 這里,其實(shí)我主要要說明的就是屬性的賦值方式用self.xxx=xxxx和xxx=xxxx是完全不同的賦值方式,大家切記!
四、autorelease對象
autorelease對象就是自動釋放對象,大家可能會疑惑,能自動釋放,我還管理干嘛,我都用自動釋放算了,事實(shí)不是這樣的,自動釋放確實(shí)好用,但是自己管理內(nèi)存才能讓項目占用更小的資源,跑起來更流暢,大家可以手動管理加autorelease一起來使用,我先講解一下autorelease對象到底是什么個情況。
首先,告訴大家autorelease對象什么時候才會被釋放。
在main函數(shù)里有一個autorelease pool,自動釋放池,所以在這個自動釋放池里的autorelease對象都會在自動釋放池結(jié)束的時候全部被釋放。
大家可能會問了,“難道所有的autorelease對象都是在程序退出的時候才被釋放?”,答案當(dāng)然不是,其實(shí)main函數(shù)中只是一個程序中眾多自動釋放池中的一個,每個runloop都會隱性的創(chuàng)建一個自動釋放池,啥是一個runloop?每個UIView創(chuàng)建、delegate回調(diào)等等都會創(chuàng)建一個自動釋放池,記得這個“等等”,意思就是有很多(如果大家想要詳細(xì)了解runloop,可以去google)。所以大家不用擔(dān)心autorelease對象不會被釋放。
很多系統(tǒng)的方法,比如[NSArray array]、[NSString stringformat]等等返回的對象都是autorelease對象,這些對象是不需要手動釋放的,如果手動釋放會導(dǎo)致程序崩潰!切記!,原則就是系統(tǒng)中所有沒有使用alloc、copy、retain來創(chuàng)建的對象都是autorelease對象,大家千萬別手動release!
轉(zhuǎn):http://blog.csdn.net/tt5267621/article/details/7632004
總結(jié)
- 上一篇: 高考前几天我们应该干什么?
- 下一篇: android:installLocat