ios記憶體管理隨筆

來源:互聯網
上載者:User

以下是我所總結的一些常見記憶體管理需要注意的方面,並沒有嚴格意義上的資料來源,可能有些部分有歧義,不太正確或遺漏,大家可以和我說說,共同進步。

按照這樣方式來使用的話,確實可以大大減少記憶體方面的問題,錯誤使用記憶體導致的崩潰也會少點。 

這裡記錄下,方便以後參考,也為大家提供個借鑒。

1. 保持對象的屬性/成員變數和對象本身的引用計數保持一致

a) 成員變數初始化時,不應該用autorelease的,如果是autorelease,則最好要retain一下,保持引用計數為1,然後在dealloc中釋放。

b) 對於屬性,除自訂的setter方法和dealloc之外,都需要使用self.testProperty=@"testPropert"的方式來進行賦值,這樣可以保持自己控制的引用計數始終為1;否則則需要在每次賦值之前都進行release。如

[_testProperty release];

_testProperty = testProperty;

c) 對應於a),所有的成員變數都需要在dealloc中進行釋放。

d) 每次成員變數release之後,除非立馬進行賦值,否知需要將其置為nil,防止其他引用的地方無法對其進行判斷。

   dealloc中可以酌情處理,關於成員變數,不設定為nil也無妨。簡單的處理方式可以將dealloc中所有的釋放的變數都置為nil。

e) 屬性中所有的obj-c對象都應該設定為retain(除delegate外),對其引用計數進行+1操作,而不要使用assign。

對於類似於BOOL,int,以及Core**架構等則需要使用assign,不需要更改引用計數。

但是delegate等需要使用assign來進行屬性聲明,當前對象不應該管理代理程式對象的引用計數。

如:

@property (nonatomic, copy)   NSString*testProperty;

@property (assign)      BOOLflag;

@property (assign)      id<property>delegate;

f) 基本原則,誰分配,誰釋放。在和C架構互動使用時更應該注意。 

g) 注意在struct中使用obj-c對象的記憶體釋放問題,確保在free的時候將引用計數變為0,或已經是autorelease。

2. 屬性關鍵字的使用

a) retain和copy的區別

retain的產生的程式碼類似於如下:

- (void)setTestProperty:(id)testProperty{    if(_testProperty != testPropert)    {        [_testProperty release];        _testProperty = [testPropert retain];    }}

所以retain會釋放舊的值,然後設定為新的值,並retain,自身保持其引用計數。從此也可以看出,成員變數_testProperty引用外部變數時,始終會retain一次。

copy會產生一個新的對象指標,例如

一個NSString*的地址為0x0011,內容為@"testProperty"

copy操作之後,產生一個新的NSString *,其地址為0x1122,內容相同,新的對象的retainCount為1,不對舊對象進行操作,故舊對象沒有任何變化。

所以可以理解為retain其實是對指標的拷貝,copy是對內容的拷貝。但是由於NSArray,NSDictionay對象等,由於其內容也是指標,故拷貝的其實是數組內部的指標。

也即一般情況下,都可以將NSString 的屬性聲明為copy的。如@property (nonatomic, copy) NSString *test; 

b) assign,nonatomic

assign, Setter方法為直接賦值,不進行retain操作,通常是為了基本類型或像delegate之類的引用(防止出現循環參考問題)。

nonatomic, 非原子性訪問,不加同步,多線程並發訪問會提升效能,如果不加此屬性,預設為原子型事務。鎖被加到所屬對象執行個體級。nonatomic使用也較多。

c) @synthesize xxx; 為xxx產生相應的Setter/Getter方法

d) 系統會預設分配一個沒有對應變數的屬性,如下樣本:

@property (nonatomic, copy) NSString *testProperty;

@synthesize testProperty;

樣本中並未聲明任何變數對應與testProperty屬性,但是仍然可以使用self.testProperty來進行賦值和取值。

這是因為系統會預設分配一個_testProperty的變數來與之對應。但建議還是添加一個成員變數,這樣更為清晰。 

3. 在obj-c編程中使用了CoreGraphics.framework,CoreTelephony.framework等C架構

該類C架構採用CFRelease/CFRetain去控制對象的生命週期。其可以與obj-c對象直接轉換。例如:

NSString *str = [NSStrig stringWithFormat:@"%@", @"abcdefg"];

CFStringRef ref = (NSString *)[str retain];

此時需要使用CFRelease(ref);來對其進行釋放; 

4. 直接使用C語言,則需要自己去控制記憶體的分配和釋放

malloc和free需要嚴格對應,如果作為函數參數的話,需要使用指向指標的變數來作為函數參數。外部提供釋放。

關於這塊,建議看看聖經《深入理解電腦系統》,上面講得非常透徹與詳細。 

5.  特殊情境

a) @"123", 以及initWithString等產生的引用計數都是非常大的。對此執行的release操作只是為了與之前的init對應,並不會真正的釋放

b) 對象release之後,不會立刻釋放,如:

[obj release];

NSLog(@"obj = %@", obj); // 這句話不會導致崩潰

NSLog(@"obj = %@", obj); // 此時的調用會導致崩潰

c)NSAutoreleasePool的效能問題

NSAutoreleasePool也會佔用一定的效能,在XCode4.2中預設使用的編譯期支援@autoreleasepool{}塊來代替NSAutoreleasePool,其效能相對於

NSAutoreleasePool來說,有較大的提升(記得曾經看過一份文檔說會提升6倍以上)。

by yytong

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.