block聲明/定義
- block的作用:保存一段代碼
// 聲明:返回值(^block變量名)(參數(shù))
void(^block)();
// 定義
// 方式一:
void(^block1)() = ^(){
NSLog(@"調(diào)用block1");
};
// 調(diào)用Block,就會去查看下Block保存代碼
block1();
// 方式二:block如果沒有參數(shù),可以省略()
// void(^)()
void(^block2)() = ^{
};
// 方式三:block定義中,返回值可以省略
// 類型:int(^)()
int(^block3)() = ^int{
return 2;
};
添加block屬性
// Block怎么聲明.就怎么定義屬性
// block:屬性名
@property (nonatomic ,strong) void(^block)();
block內(nèi)存管理(非ARC)
-
首先了解內(nèi)存的五大區(qū):
- 堆:需要手動管理內(nèi)存
- 棧:不需要手動管理內(nèi)存,代碼塊一過,會自動清空棧里面內(nèi)存
- 方法區(qū)(代碼區(qū))
- 全局區(qū)(靜態(tài)區(qū))
- 常量區(qū)
-
如何判斷非ARC環(huán)境:
- 重寫dealloc,調(diào)用super,ARC中不能調(diào)用[super dealloc]
- 判斷下是否可以調(diào)用retain,release等等
-
非ARC開發(fā)中注意
- 訪問屬性,不要直接使用_,而是set,get方法去訪問
- 非ARC中沒有weak-->assign ,strong-->retain
block是對象嗎?官方文檔,block是對象
-
非ARC環(huán)境,block怎么去管理內(nèi)存
- block沒有訪問外部局部變量的時候,存放到全局區(qū)
- block訪問了外部局部變量,block放到棧里面
- 只要block訪問的變量,是整個app都在的變量,那么肯定在全局區(qū)
- 在非ARC中,不能使用retain引用Block,使用retain之后不會將block放在堆中,在非ARC中只能使用copy,才會把block放在堆中
block內(nèi)存管理(非ARC)
- block訪問外部局部變量,block存放堆里面
- 可以使用strong去引用
- ARC中,默認(rèn)局部對象變量都是強(qiáng)指針,但是如果沒有其他強(qiáng)指針引用的話過了代碼所在的大括號就會被銷毀
block循環(huán)引用
- (void)viewDidLoad {
[super viewDidLoad];
int a = 0;
// Block循環(huán)引用,跟block調(diào)用沒有關(guān)系
// block只要訪問外部強(qiáng)指針對象變量,就會對這個變量進(jìn)行強(qiáng)引用.
__weak typeof(self) weakSelf = self;
_block = ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2* NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"延遲打印%@",strongSelf);
});
};
_block();
}
set方法內(nèi)存管理
- retain需要使用的對象
- release之前的對象
- 只有傳入的對象和之前的不同才需要release和retain
- (void)setRoom:(Room *)room
{
// 避免過度釋放
if (room != _room)
{
// 對當(dāng)前正在使用的房間(舊房間)做一次release
[_room release];
// 對新房間做一次retain操作
_room = [room retain];
}
}
block變量傳遞
//打印結(jié)果為5:值傳遞
- (void)viewDidLoad {
[super viewDidLoad];
int a = 5;
void(^block)() = ^{
NSLog(@"%d",a);
};
a = 10;
block();
}
//打印結(jié)果為10:指針傳遞
- (void)viewDidLoad {
[super viewDidLoad];
static int a = 5;
void(^block)() = ^{
NSLog(@"%d",a);
};
a = 10;
block();
}
//打印結(jié)果為10:指針傳遞
- (void)viewDidLoad {
[super viewDidLoad];
__block int a = 5;
void(^block)() = ^{
NSLog(@"%d",a);
};
a = 10;
block();
}
//打印結(jié)果為10,指針傳遞
static int a = 5;
- (void)viewDidLoad {
[super viewDidLoad];
void(^block)() = ^{
NSLog(@"%d",a);
};
a = 10;
block();
}
- 總結(jié):當(dāng)是全局變量,或者局部變量被static或__block修飾,那么block塊訪問外界變量就是指針傳遞,普通的局部變量就是值傳遞
block當(dāng)做參數(shù)去使用
- 為什么要把block當(dāng)做參數(shù)去使用
- 使用場景: 當(dāng)自己封裝一個類的時候,有些事情由外部決定,但是什么時候去做,由內(nèi)部決定,這時候采取使用block
- 需求:封裝一個計算器,提供一個計算方法,怎么計算由外界去決定,什么時候計算,自己管理
//控制器當(dāng)中的代碼
- (void)viewDidLoad {
[super viewDidLoad];
//創(chuàng)建一個計算器管理者
CalculateManager *manager = [[CalculateManager alloc] init];
[manager calculateManager:^(int result){
result = result + 5;
result = result * 5;
return result;
}];
NSLog(@"%d",manager.result);
}
//計算機(jī)管理者類當(dāng)中提供的方法,_result為管理者的屬性
-(void)calculateManager:(int(^)(int))block
{
//相當(dāng)于執(zhí)行
// ^(_result){
// result = result + 5;
// result = result * 5;
// return result;
// }
_result = block(_result);
}
block當(dāng)做參數(shù)返回
- 以后只要看到調(diào)用方法后面接(),就是把block當(dāng)做返回值去使用
- (void)viewDidLoad {
CalculateManager *manager = [[CalculateManager alloc] init];
//讓計算器不斷的累加
manager.add(5).add(5).add(5).add(5);
NSLog(@"%zd",manager.result);
}
-(CalculateManager *(^)(NSInteger))add
{
return ^(NSInteger value){
_result += value;
return self;
};
}