1.Block基本用法:
block聲明
返回值(^block變量名)(參數(shù))
void(^block)();
block定義
//第一種
void(^block1)() = ^{
};
// 第二種,如果沒有參數(shù),參數(shù)可以隱藏,如果有參數(shù),必須寫,而且必須要有參數(shù)變量名
void(^block2)(int) = ^(int a){
};
// 第三種,不管有沒有返回值,都可以省略
int(^block3)() = ^int{
return 3;
};
-
block調(diào)用
block1();
2.Block別名:
// 類型別名:BlockType
typedef void(^BlockType)();
3.定義為屬性
// block如何聲明,就如何定義成屬性
@property (nonatomic, strong) void(^block)();
4.應(yīng)用地點(diǎn)
- Block可以在一個(gè)方法中定義, 在另外一個(gè)方法調(diào)用
- Block可以在一個(gè)類中定義, 在另外一個(gè)類中調(diào)用
5.Delegate傳值
5.1.頭文件中生成協(xié)議,聲明代理展姐,
@protocol ModalViewControllerDelegate <NSObject>
@optional
// 設(shè)計(jì)方法:想要代理做什么事情
- (void)modalViewController:(ModalViewController *)modalVc sendValue:(NSString *)value;
@end
@interface ModalViewController : UIViewController
@property (nonatomic, weak) id<ModalViewControllerDelegate> delegate;
@end
5.2.m文件中,傳值給ViewController
if ([_delegate respondsToSelector:@selector(modalViewController:sendValue:)]) {
[_delegate modalViewController:self sendValue:@"123"];
}
5.3.想要得到值的控制器中息裸,遵循協(xié)議舀锨,成為代理岭洲,重寫代理方法
@interface ViewController ()<ModalViewControllerDelegate>
modalVc.delegate = self;
// 重寫代理方法
- (void)modalViewController:(ModalViewController *)modalVc sendValue:(NSString *)value{
}
6.Block傳值
6.1.頭文件中聲明Block屬性
@property (nonatomic, strong) void(^block)(NSString *value);
6.2.m文件中,傳值給ViewController
if (_block) {
_block(@"123");
}
6.3.想要得到值的控制器中坎匿,定義Block
ModalViewController *modalVc = [[ModalViewController alloc] init];
modalVc.block = ^(NSString *value) {
NSLog(@"%@",value);
};
7.Block是不是對(duì)象?
- 答案是肯定的盾剩。
8.MRC中Block內(nèi)存管理
- Block引用外部局部變量在棧,否則在全局區(qū)替蔬。
- Block只能用copy不能用retain告私,用copy才在堆中。
9.ARC中Block內(nèi)存管理
- Block只要引用外部局部變量就在堆, 否則在全局區(qū)承桥。
- Block最好使用strong驻粟,不用copy。他們的結(jié)果是相同的凶异,但是copy的內(nèi)部處理要比strong麻煩得多蜀撑,長(zhǎng)此以往性能較低。
10.由Block引起的內(nèi)存泄漏
10.1.block循環(huán)引用場(chǎng)景:
- self強(qiáng)引用了block剩彬,block里面也強(qiáng)引用了self(block會(huì)自動(dòng)把block塊內(nèi)的強(qiáng)指針強(qiáng)引用):
@property (nonatomic, strong) void(^block)();
_block = ^(){
//_name相當(dāng)于 self -> name, 所以還是有self的
_name = @"123";
};
- 解決方案
__weak typeof(self) weakSelf = self;
_block = ^(){
weakSelf.name = @"123";
};
10.2.因?yàn)閎lock酷麦,self不被銷毀場(chǎng)景:
- 當(dāng)其他對(duì)象(可能是全局變量)強(qiáng)引用了block,block中又強(qiáng)引用了self喉恋。也會(huì)導(dǎo)致self不能被銷毀沃饶,但這個(gè)不是循環(huán)引用。
- 解決方案:
__weak typeof(self) weakSelf = self;
11.然而有時(shí)候轻黑,block中用weakSelf不安全绍坝。為什么?
__weak typeof(self) weakSelf = self;
- 因?yàn)槿绻鸼lock中有一個(gè)延遲執(zhí)行的block苔悦,block中又使用了weakSelf轩褐。執(zhí)行時(shí)候self很可能已經(jīng)被銷毀(block里面對(duì)他是弱引用)。
- 解決方案
__strong typeof(weakSelf) strongSelf = weakSelf;
12.Block使用場(chǎng)景
12.1.Block變量傳遞
- 局部變量, 是值傳遞
- 靜態(tài)變量,全局變量,__block修飾的變量, 都是指針傳遞
__block int a = 3;
void(^block)() = ^{
NSLog(@"%d",a);
};
a = 5;
block();
12.2.Block作為參數(shù)傳遞
- (void)cacultor:(NSInteger (^)(NSInteger))cacultorBlock{
if (cacultorBlock) {
_result = cacultorBlock(_result);
}
}
CacultorManager *mgr = [[CacultorManager alloc] init];
[mgr cacultor:^(NSInteger result){
result += 5;
result += 6;
result *= 2;
return result;
}];
12.3.Block作為返回值
CalculatorManager *mgr = [[CalculatorManager alloc] init];
mgr.add(5).add(5).add(5).add(5);
- (CalculatorManager *(^)(int))add{
return ^(int value){
_result += value;
return self;
};
}