Objective-C中的block有多种定义和使用方法.
作为property
@property (nonatomic, copy) int (^myBlock)(int a, int b);
block代码体:
_myBlock = ^int (int a, int b) {
return a + b;
};
使用:
sum = _myBlock(10, 20);
使用typedef
typedef int (^MyBlock)(int a, int b);
MyBlock myBlock = ^int (int a, int b) {
return a * b;
};
使用:
int sum = myBlock(10, 20);
作为变量
int (^myBlock) (int a, int b) = ^int (int a, int b) {
return a - b;
};
int sum = myBlock(10, 20);
此时myBlock可作为变量自由传递, 调用的时候myBlock(10, 20);即可.
如果想在block中对当前局部变量进行修改的话, 需要使用__block:
__block int sum = 0;
int (^myBlock)(int a, int b) = ^int (int a, int b) {
sum = a + b;
return sum;
}
block默认可访问局部变量sum, 而不能修改, 以防出现循环引用的情况.
而__block对象在block中不会被其强引用一次, 所以不会出现循环引用.
__block与__weak
以上可知, 声明block的时候只是把该sum局部变量复制了一份, 因此若其是一个指针, 则在block中修改其指向的内容不需要加__block.
__block修饰对象和基本数据类型, 而__weak只能修饰对象.
__block对象可在block中修改(重新赋值), 而__weak不行.
因此, 对于类的对象, 若要在block中对其属性进行修改, 需要使用__weak. 如:
__weak MyClass *weakSelf = self;
_myBlock2 = ^(NSInteger count) {
weakSelf.count = count;
}
作为方法调用的参数
预先声明MyBlock及属性myBlock2,
typedef int (^MyBlock)(int a, int b);
@property (nonatomic, copy) MyBlock myBlock2;
定义方法methodTakeBlock接收MyBlock.
- (int)methodTakeBlock:(MyBlock)block {
int sum = 0;
if (block) {
sum = block(10, 20);
}
return sum;
}
则调用该方法的时候, 在其参数中实现该MyBlock实体:
sum = [self methodTakeBlock:^int (int a, int b) {
return b / a;
}];
这种方式仅在implementation中即可.
在方法的声明中写明block类型
在interface中:
// 方法调用的参数
- (int)method2TakeBlock:(int (^) (int a, int b))block;
在implementation中:
- (int)method2TakeBlock:(int (^)(int, int))block {
int sum = 0;
if (block) {
sum = block(10, 20);
}
return sum;
}
调用方法:
sum = [self method2TakeBlock:^int(int a, int b) {
return a * b - b;
}];
在ViewController之间传递数据
在TestViewController.h中定义一个block, 用于从TestViewController跳转至ViewController时修改ViewController中的label内容:
#import <UIKit/UIKit.h>
@interface TestViewController : UIViewController
typedef void(^BlockUpdateBtnTitle)(NSString *);
@property (nonatomic, copy) BlockUpdateBtnTitle blockUpdateBtnTitle;
@end
该block接收一个NSString参数.
点击button触发以下动作
- (IBAction)action:(UIButton *)sender {
if (_blockUpdateBtnTitle) {
_blockUpdateBtnTitle(@"value changed by block");
}
[self dismissViewControllerAnimated:NO completion:nil];
}
在ViewController.m中传递block实体, 注意其接收参数要与定义的一致:
- (IBAction)action:(UIButton *)sender {
TestViewController *testVC = [[TestViewController alloc] init];
__weak ViewController *weakSelf = self;
testVC.blockUpdateBtnTitle = ^(NSString *btnTitle) {
weakSelf.lb.text = btnTitle;
};
[self presentViewController:testVC animated:NO completion:nil];
}
点击button跳转至TestViewController中, 在TestViewController中执行该blockUpdateBtnTitle, 进而修改ViewController中label的内容.
因在block中要对ViewController中的属性进行修改, 因此可使用__weak来防止循环引用.