IOS開發小記-內存管理

    關於IOS開發的內存管理的文章已經不少了,所以系統的知識點就不寫了,這裏我寫點平時工做遇到的疑問以及解答作個總結吧,相信也會有人遇到相同的疑問呢,歡迎學習IOS的朋友請加ios技術交流羣:190956763,共同窗習,共同進步!html

    假如在.h文件裏,定義一個變量@property (nonatomic,retain) AController  *aController;ios

    疑問1:建立對象時候,通常會使用alloc,new,copy或者mutalbeCopy等方法,web

    哪一種寫法是正確的?安全

    A self.aController=[[AController alloc] init];多線程

    B self.aController=[[[AController alloc] init] retain];函數

    C self.aController=[[[AController alloc] init] autorelease];post

    D self->aController=[[AController alloc] init];學習

    答案:C,D   引用計數的主要接口alloc,allocwithzone,new(帶初始化) 爲對象分配內存,retainCount爲「1」,並返回此實例,而調用self.aController,self自己有幹了活,他把_aController這個變量至關於又retain一下,所以A的retaincount已是2了,已經泄露了!所以不須要B這樣retain了,加autorelease的話,就會把剛纔新建那塊內存自動釋放掉的,若是用D話,沒有執行aController的setter方法,由於此時retainCount爲「1」,因此D也是正確的,C的話也能用,可是不是好的用法ui

    疑問2:在dealloc方法中,這麼寫有問題嗎?atom

- (void)dealloc{
    [self.aController release];
    self.aController = nil;
    [super dealloc];
}

    答案:這裏不須要release了,由於self.aController = nil;已經調用了release了,固然也能夠這麼寫

- (void)dealloc{
    [self->aController release];
    self->aController = nil;
    [super dealloc];
}

解釋:對於set method來講,用synthesize來讓系統幫咱們生成的set方法和以下的相似:

- (void)setAbc:(id)newAbc
{
      if(_abc != newAbc){
           [_abc release];
           _abc = [newAbc retain]; //是retain仍是copy取決於你property聲明時的attributes  
       }
}

若是新值和成員相等,就不須要進行重複的賦值了,不等的話,須要把新值賦給成員,同時,成員_abc原來的內容就不須要了,這裏要先調用release進行釋放。(這個具體的緣由在那本講Objective-C的書中寫的很清楚,請查看)。

所以在這裏,調用self.abc = nil;
就等於已經調用了[_abc release];  和_abc = nil;

self.abc = nil;和[_abc release]; 都不必定釋放對象,由於該對象還可能被別的引用,這裏的操做的意圖就是:別的地方用沒用_abc我不知道,在這裏的_abc我不用了。

爲何release後還要設置nil呢?由於是這樣的,若是引用 計數等於0還對該對象進行操做,則會出現內存訪問失敗,crash,因此儘可能設置爲nil,可是單純設置爲nil,若是retaincount不是0的話,內存同樣泄露的,所以應該設置nil的時候,先保證變量的retaincount是0了

疑問3:爲何有些變量不用考慮retain,release呢?

NSString *str1 = @」constant string」;

str1retain count是個很大的數字。Objective-C對常量字符串作了特殊處理。

固然,若是你這樣建立NSString,獲得的retain count依然爲1

NSString *str2 = [NSString stringWithFormat:@」123」];

實際上對於 [NSString stringWithFormat:] 這類構造函數返回的對象都是autorelease的,因此也不用考慮retain,release

疑問4:在ARC的狀況下,按說不用本身在考慮release了,爲何還會有dealloc方法存在呢?

答案:雖然在ARC下,不用考慮release了,可是咱們可能還要釋放一些其餘的東西,好比delegate,關閉定時器,關閉gps定位等,另外若是在ARC下,咱們本身不放心,爲了安全,本身釋放變量也沒有什麼錯誤發生!另外不用再調用[super dealloc]了

好比在ARC下,咱們可能會這麼寫

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [self.closeButtonTimer invalidate];
    [self.webView setDelegate:nil];
    [self setLocationDetectionEnabled:NO];
}

注意:好比Delegate,若是不在dealloc中釋放它,若是頁面有多線程的調用,好比開闢個線程從網上down圖片子類的,它down下來後須要找這個頁面,可是可能用戶操做比較快,好比點了後退按鈕,這時候頁面可能已經銷燬了,因而就致使頁面崩潰了,因此dealloc中要釋放掉delegate

疑問5:怎麼能知道哪裏內存泄露了呢?

這個就不詳細解釋了,看相關的帖子說的很詳細了

http://www.cocoachina.com/newbie/basic/2012/1204/5242.html

疑問6:聲明爲IBOutlet屬性的,在MRC中應該retain仍是assign?在ARC中應該是strong仍是weak?

 在MRC中,應該是retain的,由於IBOutlet自己就是retain的

任何一個被聲明爲IBOutlet而且在Interface Builder裏被鏈接到一個UI組件的成員變量,會被額外retain一次。
常見的情形如

IBOutlet UILabel *label;

這個label在Interface Builder裏被鏈接到一個UILabel。此時,這個label的retainCount爲2。
因此,只要使用了IBOutlet變量,必定須要在dealloc或者viewDidUnload裏release這個變量。

在ARC中,property,咱們將其申明爲weak(事實上,若是沒有特別意外,除了最頂層的IBOutlet意外,本身寫的outlet都應該是weak)。經過加載xib獲得的用戶界面,在其從xib文件加載時,就已是view hierarchy的一部分了,而view hierarchy中的指向都是strong的。所以outlet所指向的UI對象不該當再被hold一次了。將這些outlet寫爲weak的最顯而易見的好處是你就不用再viewDidUnload方法中再將這些outlet設爲nil了(不然就算view被摧毀了,可是因爲這些UI對象還在被outlet指針指向而沒法釋放)。

參考:

http://www.16kan.com/post/214006.html

http://www.ityran.com/archives/1234

疑問7:在ARC在,若是用retain,和用strong有什麼區別?

retain關鍵字在ARC中是依舊可用的,它在ARC中所扮演的角色和strong徹底同樣。爲了不迷惑,最好在須要的時候將其寫爲strong,那樣更符合ARC的規則。

相關文章
相關標籤/搜索