Block
- 让我们先来了解下Block是怎么定义的:
返回值类型(^block变量名)(形参列表) = ^(形参列表) {
};
调用Block保存的代码
block变量名(实参);
- 接下来举两个例子来了解下block
//(1)定义无参无返回值的Block(^后面的括号在无参数时可以省略)
void (^MyBlock)() = ^(){
printf("no number");
};
MyBlock();
//(2)定义名为myBlock的代码块,返回值类型为int
int mutiplier = 7;
int (^myBlock)(int) = ^(int num){
return num*mutiplier;
};
//使用定义的myBlock
int newMutiplier = myBlock(3);
printf("newMutiplier is %d",myBlock(3));
-
block也可以在方法外面定义:只需要在viewDidLoad里调用block
- (void)viewDidLoad {
[super viewDidLoad];self.view.backgroundColor = [UIColor whiteColor]; printNumBlock(4); } //定义在-viewDidLoad方法外部 //(2)定义一个有参数,没有返回值的Block void (^printNumBlock)(int) = ^(int num){ printf("int number is %d",num); };
-
以上block可以总结一下几点
(1)在类中,定义一个Block变量,就像定义一个函数;(2)Block可以定义在方法内部,也可以定义在方法外部;
(3)只有调用Block时候,才会执行其{}体内的代码
__block关键字的引用
- 咱们先来看两个例子
//将Block定义在方法内部
//作为变量
此时myBlock可作为变量自由传递, 调用的时候myBlock(10, 20);即可.
int (^myBlock) (int a, int b) = ^int (int a, int b) {
return a - b;
};
int dum = myBlock(10, 20);
NSLog(@"%d",dum);
-------------------------------------------------------
如果想在block中对当前局部变量进行修改的话, 需要使用__block,如下:
__block int x = 100;
void (^sumXAndYBlock)(int) = ^(int y){
x = x + y;
printf("改变后X的值 %d",x);
};
sumXAndYBlock(50);
如果不用__block修饰Xcode会提示x变量错误信息:Variable is not assigning (missing __block type)
-------------------------------------------------------
__block int mul = 0;
int (^MulBlock)(int a, int b) = ^int (int a, int b) {
mul = a * b;
return mul;
};
MulBlock(10,10);
NSLog(@"%d", mul);
block默认可访问局部变量mul, 而不能修改, 以防出现循环引用的情况.
而__block对象在block中不会被其强引用一次, 所以不会出现循环引用.
所以说如果在Block的{}体内,修改外部变量就需要用__block修饰。
__block和
__weak
以上可知, 声明block的时候只是把该sum局部变量复制了一份, 因此若其是一个指针, 则在block中修改其指向的内容不需要加__block.
__block修饰对象和基本数据类型, 而__weak只能修饰对象.
__block对象可在block中修改(重新赋值), 而__weak不行.因此, 对于类的对象, 若要在block中对其属性进行修改, 需要使用__weak.代码如下:
定义两个属性
@interface ViewController ()
@property(nonatomic,copy)void (^myBlock2)(NSInteger);
@property(nonatomic,assign)NSInteger count;
@end
//block修改值
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
__weak typeof(self) weakself = self;
_myBlock2 = ^(NSInteger count) {
weakself.count = count;
NSLog(@"%ld",weakself.count);
};
_myBlock2(10);
}
如果不用__weak修饰则会出现如下情况
block传值
block传值用到的地方有很多,我们就来举个例子看下怎么实现的吧
首先有两个控制器ViewController和SubViewController。从后者向前者传值-
在SubViewController.h中定义block
#import <UIKit/UIKit.h>
//blocktypedef void (^ReturnTextBlock)(NSString *showtext); @interface SubViewController : UIViewController @property (nonatomic, copy) ReturnTextBlock returnTextBlock; - (void)returnText:(ReturnTextBlock)block; @end
-
在SubViewController.m中实现方法
-(void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; if (self.returnTextBlock != nil) { self.returnTextBlock(@"利用Block传值"); } - (void)returnText:(ReturnTextBlock)block { self.returnTextBlock = block; }
-
在ViewController.m中触发事件调用block,实现block的回调
-(void)btnClick:(UIButton *)sender{ SubViewController *sub = [[SubViewController alloc]init]; //block实现方法 [sub returnText:^(NSString *showText) { _delegateLabel.text = showText; }]; [self.navigationController pushViewController:sub animated:YES]; }