Objective-C中的block有多種定義和使用方法.
@property (nonatomic, copy) int (^myBlock)(int a, int b);
block代碼體:
_myBlock = ^int (int a, int b) {
return a + b;
};
使用:
sum = _myBlock(10, 20);
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的時候只是把該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中即可.
在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;
}];
在TestViewController.h中定義一個block, 用於從TestViewController跳轉至ViewController時修改ViewController中的label內容:
#import
@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來防止循環引用.