Block,block是什麼意思
Block簡介
Block使用情境,可以在兩個介面的傳值,也可以對代碼封裝作為參數的傳遞等。用過GCD就知道Block的精妙之處。
Block是一種比較特殊的資料類型。它可以儲存一段代碼,在合適的時候取出來調用。
Block的修飾
ARC情況下
1.如果用copy修飾Block,該Block就會儲存在堆空間。則會對Block的內部對象進行強引用,導致循環參考。記憶體無法釋放。
解決方案:
建立一個指標(__weak typeof(Target) weakTarget = Target )指向Block代碼塊裡的對象,然後用weakTarget進行操作。就可以解決循環參考問題。
2.如果用weak修飾Block,該Block就會存放在棧空間。不會出現循環參考問題。
MRC情況下
用copy修飾後,如果要在Block內部使用對象,則需要進行(__block typeof(Target) blockTarget = Target )處理。在Block裡面用blockTarget進行操作。
typedef int (^SumP)(int,int);//用typedef定義一個block類型
//利用typedef定義block來建立一個block變數
SumP sumblock1 = ^(int a,int b){
return a - b;
};
int d = sumblock1(10,5);
NSLog(@"d = %d",d);
Block的定義格式
傳回值類型(^block變數名)(形參列表) = ^(形參列表) {
};
調用Block儲存的代碼
block變數名(實參);
預設情況下,Block內部不能修改外面的局部變數
Block內部可以修改使用__block修飾的局部變數
Block的模式
1.無參數無傳回值的Block
2.有參數無傳回值的Block
3.有參數有傳回值的Block
Block簡單用法舉例
無參數無傳回值的Block
/**
* 無參數無傳回值的Block
*/
-(void)func1{
/**
* void :就是無傳回值
* emptyBlock:就是該block的名字
* ():這裡相當於放參數。由於這裡是無參數,所以就什麼都不寫
*/
void (^emptyBlock)() = ^(){
NSLog(@"無參數,無傳回值的Block");
};
emptyBlock();
}
有參數無傳回值的Block
/**
* 調用這個block進行兩個參數相加
*
* @param int 參數A
* @param int 參數B
*
* @return 無傳回值
*/
void (^sumBlock)(int ,int ) = ^(int a,int b){
NSLog(@"%d + %d = %d",a,b,a+b);
};
/**
* 調用這個sumBlock的Block,得到的結果是20
*/
sumBlock(10,10);
有參數有傳回值的Block
/**
* 有參數有傳回值
*
* @param NSString 字串1
* @param NSString 字串2
*
* @return 返回拼接好的字串3
*/
NSString* (^logBlock)(NSString *,NSString *) = ^(NSString * str1,NSString *str2){
return [NSString stringWithFormat:@"%@%@",str1,str2];
};
//調用logBlock,輸出的是 我是Block
NSLog(@"%@", logBlock(@“我是",@"Block"));
Block結合typedef使用
自己定義一個Block類型,用定義的類型去建立Block,更加簡單便捷。
這裡舉例一個Block回調修改上一下介面的背景顏色。
ViewController1 控制器1,ViewController2 控制器2
控制器1跳轉到控制器2,然後在控制器2觸發事件回調修改控制器1的背景顏色為紅色。
Demo
ViewController2的實現
#import <UIKit/UIKit.h>
@interfaceViewController2 : UIViewController
/**
* 定義了一個changeColor的Block。這個changeColor必須帶一個參數,這個參數的類型必須為id類型的
* 無傳回值
* @param id
*/
typedefvoid(^changeColor)(id);
/**
* 用上面定義的changeColor聲明一個Block,聲明的這個Block必須遵守聲明的要求。
*/
@property (nonatomic, copy) changeColor backgroundColor;
@end
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//聲明一個顏色
UIColor *color = [UIColor redColor];
//用剛剛聲明的那個Block去回調修改上一介面的背景色
self.backgroundColor(color);
}
ViewController1的實現
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
ViewController2 *vc =[[ViewController2 alloc]init];
// 回調修改顏色
vc.backgroundColor = ^(UIColor *color){
self.view.backgroundColor = color;
};
[self.navigationController pushViewController:vc animated:YES];
}