iOS --- 關於block的常見使用方法
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修飾對象和基礎資料型別 (Elementary Data Type), 而__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 @interface TestViewController : UIViewControllertypedef 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來防止循環參考.