文章出處

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

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

    疑問1:創建對象時候,一般會使用alloc,new,copy或者mutalbeCopy等方法,

    哪種寫法是正確的?

    A self.aController=[[AController alloc] init];

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

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

    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的話也能用,但是不是好的用法

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

- (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的規則。

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()