執行迴圈和自動釋放池關係

zhYx__發表於2017-10-10

準備工作

  • 新建Person類,將Person類的編譯環境改成MRC的.
  • 手動管理Person類的記憶體.
  • 把某個類的編譯環境改成MRC的 : -fno-objc-arc

Person類中宣告

@interface Person : NSObject

/// 名字
@property (nonatomic,copy) NSString *name;

/// 類方法例項化person物件
+ (instancetype)personWithName:(NSString *)name;

@end

Person類中實現

  • MRC開發中,所有返回id型別的類方法,都必須要使用autorelease標記成延緩釋放的物件.
  • 延遲釋放的物件,在出了作用域以後,會被新增到最近一次建立的自動釋放池中,等待被釋放.
+ (instancetype)personWithName:(NSString *)name
{
    // 這是個延遲釋放的物件
    Person *p = [[[Person alloc] init] autorelease];

    p.name = name;

    // 無法 return
//    [p release];

    return p;

    // 無法 release
//    [p release];
}

控制器中的使用

  • 宣告屬性
@interface ViewController ()

/// p1
@property (nonatomic,weak) Person *p1;
/// p2
@property (nonatomic,weak) Person *p2;

@end
  • Person類的例項化
- (void)viewDidLoad {
    [super viewDidLoad];

    self.p1 = [[Person alloc] init];
    self.p1.name = @"zs";
    NSLog(@"%@",self.p1.name);

    self.p2 = [Person personWithName:@"ls"];
    NSLog(@"%@",self.p2.name);

    // 手動建立自動釋放池,這個不是我們討論的
    @autoreleasepool {

    }
}
  • 測試物件的釋放
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSLog(@"%@",self.p1.name);
    NSLog(@"%@",self.p2.name);
}
  • 提問 :
    1. p2 什麼時候釋放的? 自動釋放池銷燬的時候釋放的.
    2. 自動釋放池什麼時候銷燬的?
    3. 自動釋放池什麼時候建立的?

執行迴圈和自動釋放池關係

  • iOS開發中的記憶體管理
    • 在iOS開發中,並沒有JAVA或C#中的垃圾回收機制
    • 在MRC中物件誰申請,誰釋放
    • 使用ARC開發,只是在編譯時,編譯器會根據程式碼結構自動新增了retain、release和autorelease.
  • 自動釋放池

    • 標記為autorelease的物件,會被新增到最近一次建立的自動釋放池中
    • 當自動釋放池被銷燬或耗盡時,會向自動釋放池中的所有物件傳送release訊息
  • 自動釋放池的建立與銷燬

    • 此處討論的自動釋放池不是我們以前手動建立的那種.是系統處理記憶體相關的.
    • 自動釋放池是什麼時候建立的?什麼時候銷燬的?
      • 建立 : 執行迴圈檢測到事件並啟動後,就會建立自動釋放池.
      • 銷燬 : 一次完整的執行迴圈結束之前,會被銷燬.
  • 執行迴圈

    • 執行迴圈 / 訊息迴圈.
    • 作用
      • 訊息迴圈保證應用程式不退出.
      • 訊息迴圈在迴圈的撲捉訊息,然後執行訊息對應的操作.

執行迴圈和自動釋放池的關係圖解

  • 什麼時候需要手動建立自動釋放池?

    • 如果在迴圈中建立了大量的臨時變數的時候需要在迴圈一開始就手動建立一個自動釋放池
    • If you write a loop that creates many temporary objects.You may use an autorelease pool block inside the loop to dispose of those objects before the next iteration. Using an autorelease pool block in the loop helps to reduce the maximum memory footprint of the application.
  • 關於自動釋放池的筆試題

for (int i = 0; i < largeNumber; ++i) {
    NSString *str = @"Hello World";
    str = [str stringByAppendingFormat:@" - %d", i];
    str = [str uppercaseString];
}

相關文章