關於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」;
str1的retain 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的規則。