AutoReleasePool
- 此處討論的
自動釋放池
不是我們以前手動創(chuàng)建的那種.是系統處理內存相關的.
自動釋放池和運行循環(huán)關系
-
iOS開發(fā)中的內存管理
- 在iOS開發(fā)中降狠,并沒有JAVA或C#中的垃圾回收機制
- 在MRC中對象誰申請,誰釋放
- 使用ARC開發(fā),只是在編譯時,編譯器會根據代碼結構自動添加了retain挥唠、release和autorelease.
-
自動釋放池
- 標記為autorelease的對象扩所,會被添加到最近一次創(chuàng)建的自動釋放池中
- 當自動釋放池被銷毀或耗盡時嫉入,會向自動釋放池中的所有對象發(fā)送release消息
自動釋放池的創(chuàng)建與銷毀
- 此處討論的
自動釋放池
不是我們以前手動創(chuàng)建的那種.是系統處理內存相關的. - 自動釋放池是什么時候創(chuàng)建的壁查?什么時候銷毀的?
- 創(chuàng)建 :
運行循環(huán)
檢測到事件并啟動后,就會創(chuàng)建自動釋放池. - 銷毀 : 一次完整的
運行循環(huán)
結束之前,會被銷毀.
- 創(chuàng)建 :
運行循環(huán)
- 運行循環(huán) / 消息循環(huán).
- 作用
- 消息循環(huán)保證應用程序不退出.
- 消息循環(huán)在循環(huán)的撲捉消息,然后執(zhí)行消息對應的操作.
- 模擬運行循環(huán)
int main(int argc, const char * argv[]) {
@autoreleasepool {
while (YES) {
// 在控制臺打印提示語
printf("請輸入你要做的操作:");
// 保存輸入的數字
int result;
// 接收控制太輸入的數組字
scanf("%d",&result);
// 判斷控制臺輸入的數字
if (0==result) {
NSLog(@"退出程序");
break;
} else if (1==result) {
NSLog(@"點擊了按鈕");
} else if (2==result) {
NSLog(@"滾動了視圖");
}
// insert code here...
// NSLog(@"Hello, World!");
}
}
return 0;
}
運行循環(huán)和自動釋放池的關系圖解

什么時候需要手動創(chuàng)建自動釋放池?
-
如果在循環(huán)中創(chuàng)建了大量的臨時變量的時候需要在循環(huán)一開始就手動創(chuàng)建一個自動釋放池
- 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.
-
如果你生成一個子線程的時候,要在線程開始執(zhí)行的時候,盡快創(chuàng)建一個自動釋放池.否則會內存泄露.因為子線程無法訪問主線程的自動釋放池.
- 自定義NSOperation和NSThread時
- If you spawn a secondary thread.You must create your own autorelease pool block as soon as the thread begins executing; otherwise, your application will leak objects. (See Autorelease Pool Blocks and Threads for details.)
關于自動釋放池的筆試題
for (int i = 0; i < largeNumber; ++i) {
NSString *str = @"Hello World";
str = [str stringByAppendingFormat:@" - %d", i];
str = [str uppercaseString];
}
// 問 : 以上代碼存在問題嗎?
延緩釋放的對象
演示延緩釋放的對象
- 新建Person類,將Person類的編譯環(huán)境改成MRC的.
- 手動管理Person類的內存.
Person類中聲明
@interface Person : NSObject
/// 名字
@property (nonatomic,copy) NSString *name;
/// 類方法實例化person對象
+ (instancetype)personWithName:(NSString *)name;
@end
Person類中實現
- 在
MRC
開發(fā)中,所有返回id
類型的類方法,都必須要使用autorelease
標記成延緩釋放
的對象. - 延遲釋放的對象,在出了作用域以后,會被添加到最近一次創(chuàng)建的自動釋放池中,等待被釋放.
+ (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);
// 手動創(chuàng)建自動釋放池,這個不是我們討論的
@autoreleasepool {
}
}
- 測試對象的釋放
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"%@",self.p1.name);
NSLog(@"%@",self.p2.name);
}
-
提問 :
-
p2
什么時候釋放的? 自動釋放池銷毀的時候釋放的. - 自動釋放池什么時候銷毀的?
- 自動釋放池什么時候創(chuàng)建的?
-