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]; }