《Objective-C 高級編程》學習筆記1-內存管理


獅子頭鎮樓

《Objective-C 高級編程》學習筆記2-Blocks
編程

《Objective-C 高級編程》學習筆記3-GCD
框架

一、什麼是自動引用計數

  • 內存管理中對引用採起自動計數的技術
  • 在編譯器中設置 ARC 爲有效狀態,就無需再次鍵入 retain 或者是 release 代碼

二、內存管理 / 引用計數

2.1   內存管理的思考方式

  • 本身生成的對象,本身所持有
  • 非本身生成的對象,本身也能持有
  • 再也不須要本身持有的對象時釋放
  • 非本身持有的對象沒法釋放


2.2   alloc/retaion/release/dealloc 實現

GNUstep 是 Cocoa 框架的互換框架函數

2.2.一、GNUstep 中 alloc 類方法實現的簡化版:post

struct obj_layout {
    NSUInteger retained;
};

+ (id)alloc {
    int size = sizeof(struct obj_layout) + 對象大小;
    struct obj_layout *p = (struct obj_layout *)calloc(1, size);
    return (id)(p + 1);
}複製代碼

2.2.二、alloc 返回對象的內存圖:學習


2.2.三、GNUstep 內存管理總結:ui

  • 在 OC 對象中存有引用計數這一整數值
  • 調用 alloc 或是 retaion 方法後,引用計數值加1
  • 調用 release 後,引用計數值減1
  • 引用計數值爲0時,調用 dealloc 方法廢棄對象

2.3   內存管理-蘋果的實現

// __CFDoExternRefOperation 函數按 retainCount/retain/release 操做進行分發調用不一樣函數
// NSObject 類的相關方法實現以下:

- (NSUInteger)retainCount {
    return (NSUInteger)__CFDoExternRefOperation(OPERATION_retainCount, self);
}

- (id)retain {
    return (id)__CFDoExternRefOperation(OPERATION_retain, self);
}

- (void)release {
    __CFDoExternRefOperation(OPERATION_release, self);
}複製代碼

GNUstep 將引用計數保存在對象佔用內存塊頭部的變量中,spa

蘋果則是保存在引用計數表的記錄中:
3d


經過內存塊頭部管理引用計數的好處:指針

  • 少許代碼便可完成
  • 可以統一管理引用計數用內存塊與對象用內存塊

經過引用計數表管理引用計數的好處:code

  • 對象用內存塊的分配無需考慮內存塊頭部
  • 引用計數表各記錄中存有內存塊地址,可從各個記錄追溯到各對象的內存塊

三、ARC 規則

3.1   全部權修飾符

OC 編程中爲了處理對象,可將變量類型定義爲 id 類型或各類對象類型:

  • 對象類型就是指向 NSObject 這樣的OC類的指針,例如「NSObject *」
  • id 類型用於隱藏對象類型的類名部分,至關於C語言中經常使用的「void *」

ARC有效時,id類型和對象類型必須附加全部權修飾符:

  • __strong
  • __weak
  • __unsafe_unretained
  • __autoreleasing

3.1.一、__strong修飾符:默認的全部權修飾符

__strong修飾符表示對對象的「強引用」。持有強引用的變量在超出其做用域時被廢棄,隨着強引用的失效,引用的對象會隨之釋放。

3.1.二、__weak修飾符:避免引用循環,弱引用不能持有對象實例

循環引用容易形成內存泄漏,內存泄漏就是應當廢棄的對象在超出其生存週期後繼續存在。

__weak修飾符,在持有某對象的弱引用時,若該對象被廢棄,則此弱引用將自動失效且處於nil被賦值的狀態。

3.1.三、__unsafe_unretained修飾符:在iOS如下中用來代替__weak

附有__unsafe_unretained修飾符的變量不屬於編譯器的內存管理對象

賦值給附有__unsafe_unretained修飾符變量的對象在經過該變量使用時,若是沒有確保其確實存在,則應用程序會崩潰。

3.1.四、__autoreleasing修飾符

ARC有效時,指定「@autoreleasepool塊」替代「NSAutoreleasePool」類,用附有 __autoreleasing 修飾符的變量替代 autorelease 方法。

不使用 __autoreleasing 修飾符也能使對象註冊到 autoreleasepool。因爲return使強引用持有的對象超出做用域會被釋放,但該對象做爲函數的返回值,編譯器會自動將其註冊到 autoreleasepool。

在訪問附有 __weak 修飾符的變量時,實際上一定要訪問註冊到 autoreleasepool 的對象。

3.2   規則

在 ARC 有效的狀況下編譯源代碼,必須遵照必定的規則:

  • 不能使用 retain/release/retainCount/autorelease
  • 不能使用 NSAllocateObject/NSDeallocateObject
  • 須遵照內存管理的方法命名規則
  • 不要顯示調用 dealloc
  • 使用 @autoreleasepool 塊替代 NSAutoreleasePool
  • 不能使用區域(NSZone)
  • 對象型變量不能做爲C語言結構體的成員
  • 顯示轉換「id」 和 「void *」

3.2.三、ARC 有效時須遵照內存管理的方法命名規則

在 ARC 無效時,用於對象 生成/持有 的方法必須遵照命名規則:

  • alloc
  • new
  • copy
  • mutableCopy

在 ARC 有效時,以上規則沒有改變。只是要追加一條命名規則:

  • init,該方法會初始化 alloc 方法返回的對象,而後原封不動地返還給調用方

3.3   屬性

當 ARC 有效時,Objective-C 類的屬性也會發生變化:

相關文章
相關標籤/搜索