一、ARC
(一)基本原理
項目:ARC0427
1.MRC:Manual Reference Counting 手動引用計數
手動添加retain、release、autorelease、super dealloc
2.ARC:Automatic Referenc Counting 自動引用計數
ARC內存管理原則:
1)有強引用指針指向的對象,不會被釋放掉
2)若沒有,就會被立刻釋放。
3.關鍵字的使用
1)系統在編譯時自動添加retain、release、autorelease、super dealloc
2)禁用retain、release、autorelease、super dealloc
使用新關鍵字strong、weak、unsafe_unretain(不常用)、__bridge
(1) strong:強引用,會對對象引用計數+1。出了作用域,就會被釋放。
(2) weak,(不常用)unsafe_unretain:弱引用,對引用計數無+-。
weak:立即被釋放。當對象釋放,指針會指向nil,不會造成程序崩潰
unsafe_unretained(不常用):當對象釋放,指針仍指向被釋放對象的內存,程序會崩潰
(3) __bridge:用于 對OC類型與CF類型 互相轉換時的內存管理。
特點:
①在ARC中使用
②不會改變ownership(內存管理權限)
方法:CFBridgingRetain
特點:交換管理權限
注意:聲明變量時,默認是strong
4.Foundation 和 CoreFoundation
1)概念
Foundation框架:定義了常用的數據類型(如OC對象 NSString、NSData、NSSet等)。
CoreFoundation框架:定義了與系統底層API打交道的數據類型(CF開頭的類型)。
2)區別
OC類型 與 CF類型 在內存結構上是相同的,即同一塊內存地址上有兩個不同的名字(NS,CF)
3)轉換
ARC下,OC與CF 要使用關鍵字__bridge 進行轉換
MRC下,OC與CF 可直接進行 強制類型轉換
(二)
項目:ARC_More0427
1.__autoreleasing:不常用,系統會自動添加
2.@autoreleasepool{}:不常用,可以替換 MRC 中的 NSAutoreleasePool
在局部大量創建自動釋放的對象時(如for循環),會使用自動釋放池。
3.移除通知:自定義類的對象被注冊為監聽者時,當該對象被釋放時,在該類的dealloc方法中移除通知
4.局部、實例、全局變量
1)局部變量:出了作用域就會被釋放
2)實例變量:dealloc中釋放
3)全局變量:程序退出時系統自動收回
在整個應用程序中都可以使用,程序退出時,才被釋放。系統管理內存。
//①聲明:
#import "AppDelegate.h"
NSString *text = @"全局變量";
//②引入:
#import "ViewController.h"
extern NSString *text;
5.屬性關鍵字的使用
1)基本數據類型:assign(或省略)
2)字符串:copy
3)對象:strong(等同于MRC中的retain)
4)代理:weak(防止循環引用)
5)控件
①拖拽:默認為weak(也可以使用strong,但沒有必要)
原因:self.view已經使用了strong關鍵字,所以沒有必要對拖拽的控件使用strong,用weak即可。
②手動:strong
6.ARC與MRC的混編
1)ARC環境下:使用第三方類庫(不支持ARC),在每個文件上加 -fno-objc-arc
2)MRC環境下:使用第三方類庫(只支持ARC),在每個文件上加 -fobjc-arc
舉例:
weak
__weak UIView *view1 = [[UIView alloc]initWithFrame:CGRectZero];
NSLog(@"1.view1 = %@",view1);//被立即釋放
{
UIView *view2 = [[UIView alloc]initWithFrame:CGRectZero];//strong
view1 = view2;//只要有一個strong,view1就不會釋放
NSLog(@"2.view1 = %@",view1);
}//view2被釋放,即view2 = nil;view1也為nil
NSLog(@"3.view1 = %@",view1);
二、Block
(一)
項目:Block_Define0427
一、局部block對象 定義格式
1.聲明
void(^blockName)(parameter list)
①無參無返回值
②有參無返回值
③有參有返回值
float(^calculateBMI)(float,float);
2.實現
blockName = ^(parameter list){ myCode };
calculateBMI = ^(float weight,float height)
{
float BMI = weight / (height *height);
return BMI;
};
3.調用
blockName(parameter list);
float bmi = calculateBMI(70,1.7);
(二)block內部使用外部變量
項目:Block_UseOutPamater
1.局部變量
1)普通局部變量
相當于copy了一個新的變量,值和原來的一樣,
block內只讀,與外部的i是兩個不同的變量
int i = 1;
2)使用__block關鍵字
block內可修改,與外部的i是同一變量
__block int block_i = 1;
2.實例變量和靜態變量
block是從變量所在的內存地址中讀取最新的值
可修改
(三)
項目:Block_MRC_Memory
1.MRC下的內存分配
1)不使用外部變量
NSGlobalBlock類型,分配在全局變量區,由系統收回
2)使用外部變量
NSStackBlock類型,分配到棧區
該block出了作用域,就由系統釋放。
3)對分配在棧區的block進行Block_copy操作
NSMallocBlock類型,分配在堆區
程序員只要不調用Block_release(...)方法,block就始終存在
2.ARC下的內存分配
系統會對棧上的block進行一次copy,拷貝到堆區,由NSStackBlock--->NSMallocBlock
使用外部變量
NSMallocBlock類型
(四)
項目:Block_MRC_Memory
UIView *view = [[UIView alloc]initWithFrame:CGRectZero];
void(^block1)() = ^()
{
view.backgroundColor = [UIColor redColor];
};
Block_copy(block1);//copy方法只對棧區的block有用
使用Block_copy使block1變為堆區
分配在堆上的block會對外部變量的引用計數+1
當block釋放時,它內部使用的外部變量的引用計數會隨之-1
造成循環引用:
block釋放時,self.retainCount會-1
self釋放時,block才會釋放(在self的dealloc方法中釋放)
防止循環引用:
在MRC環境中,使用__block修飾外部變量
在ARC環境中,使用__weak修飾
(五)
項目:Block_TransformValue0427
1.遍歷
1)遍歷數組
NSArray *array = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8"];
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"obj%d = %@",idx,obj);
if (idx == 4)
{
*stop = YES;//停止循環
}
}];
2)倒序遍歷
[array enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
}];
2.傳值
測試:alertView傳值,用block