一贩虾、block簡介
block代碼塊是在iOS4開始引入的對C語言的擴(kuò)展催烘,用來實(shí)現(xiàn)匿名函數(shù)的特性,block是一種特殊的數(shù)據(jù)類型缎罢,其可以正常定義變量伊群、作為參數(shù)、作為返回值策精,blcok還可以保存一段代碼舰始,在需要時調(diào)用。
二蛮寂、block定義
block在定義時并不會執(zhí)行內(nèi)部的代碼蔽午,只有在調(diào)用時才會執(zhí)行。
//block變量的賦值:Block變量 = ^(參數(shù)列表){函數(shù)體};
1酬蹋、無參數(shù)無返回值的block
//1及老、無參數(shù)無返回值的block
//zqqBlock是block名 無參數(shù)可省略參數(shù)列表()
//void (^zqqBlock)() = ^{};
void (^zqqBlock)() = ^(){
NSLog(@"這是無返回值無參數(shù)的block");
};
//調(diào)用
zqqBlock();
2抽莱、有參數(shù)無返回值的block
//zqqBlock是block名 NSString 是參數(shù)類型,x,y參數(shù)
void (^zqqBlock)(NSString* ,NSString*) = ^(NSString *x,NSString *y){
NSLog(@"這是無返回值有參數(shù)的block骄恶,參數(shù)是%@,%@",x,y);
};
//調(diào)用
zqqBlock(@"a",@"b");
3食铐、有參數(shù)有返回值的block
//NSString是返回類型 zqqBlock是block名 NSString 是參數(shù)類型,x,y參數(shù)
NSString* (^zqqBlock)(NSString* ,NSString*) = ^(NSString *x,NSString *y){
return [NSString stringWithFormat:@"%@+%@",x,y];
};
//調(diào)用
NSString *testStr = zqqBlock(@"a",@"b");
NSLog(@"%@",testStr);
三僧鲁、block使用
1虐呻、block重命名
利用typedef為block進(jìn)行重命名
#import "ViewController.h"
@interface ViewController ()
//定義一個無返回值無參數(shù)的block
typedef void (^zqqBlock)();
//用自定義的zqqBlock聲明一個block
@property (nonatomic, copy) zqqBlock abock;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 避免循環(huán)引用,用__weak修飾
__weak ViewController *weakSelf = self;
self.abock = ^{
weakSelf.view.backgroundColor = [UIColor redColor];
};
//調(diào)用
self.abock();
}
@end
2寞秃、block的應(yīng)用場景
block聲明屬性要用copy修飾
因?yàn)橹挥衏opy后的Block才會在堆中斟叼,棧中的Block的生命周期是和棧綁定的
<棧 :由系統(tǒng)維護(hù)的局部變量 是存在棧上的,其生命周期隨函數(shù)的生命周期>
<堆 :由程序員申請空間地址春寿,由程序員手動釋放朗涩,生命周期受到程序員控制>
使用retain也可以,因?yàn)閎lock的retain行為默認(rèn)是用copy的行為實(shí)現(xiàn)的绑改,block變量默認(rèn)是聲明為棧變量的谢床,為了能夠在block的聲明域外使用,所以要把block拷貝(copy)到堆厘线,所以說為了block屬性聲明和實(shí)際的操作一致识腿,最好聲明為copy。
block的使用:
- 反向傳值
//1.在NextViewController.h中聲明block
#import <UIKit/UIKit.h>
typedef void (^popToNextBlock)(UIColor *color);//1.別名 傳參
@interface NextViewController : UIViewController
@property (nonatomic, strong) popToNextBlock popToNextBlock;//2.聲明block
@end
//2.在NextViewController.m中定義block
#import "NextViewController.h"
-(void)popToFirstBtnClick:(id)sender{
[self.navigationController popViewControllerAnimated:YES];
if (self.popToNextBlock){
UIColor *color = [UIColor redColor];
self.popToNextBlock(color);
}
}
//上一控制器push時調(diào)用
NextViewController *nextVc = [[NextViewController alloc]init];
[self.navigationController pushViewController:nextVc animated:YES];
//調(diào)用block
__weak ViewController *weakSelf = self;
//block的回調(diào)只對最后一次賦值有效
nextVc.popToNextBlock = ^(UIColor *color){
//避免循環(huán)引用造壮,應(yīng)該使用弱引用
weakSelf.view.backgroundColor = color;
};
- 在方法中定義block 回調(diào)傳值
//1.ZqqTool.h文件
#import <Foundation/Foundation.h>
typedef void(^ZqqToolBlock)(NSString *string);
@interface ZqqTool : NSObject
//在方法中封裝block
-(void)zqqToolWithString:(NSString *)str andBlock:(ZqqToolBlock)block;
//2.ZqqTool.m文件
#import "ZqqTool.h"
-(void)zqqToolWithString:(NSString *)str andBlock:(ZqqToolBlock)block{
block(str);
}
@end
//3.調(diào)用
ZqqTool *tool = [[ZqqTool alloc]init];
[tool zqqToolWithString:@"測試" andBlock:^(NSString *string) {
NSLog(@"%@",string);
}];
- 作為參數(shù)傳遞
//1.ZqqSendBlock ZqqTool.h文件
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef void(^ZqqSendBlock)(UIColor *color);
typedef void(^ZqqToolBlock)(NSString *string);
@interface ZqqTool : NSObject
//在方法中封裝block
-(void)zqqToolWithString:(NSString *)str andBlock:(ZqqToolBlock)block;
-(void)ZqqSendBlock:(ZqqSendBlock)block;
@end
//2..ZqqTool.m文件
#import "ZqqTool.h"
@implementation ZqqTool
-(void)zqqToolWithString:(NSString *)str andBlock:(ZqqToolBlock)block{
block(str);
}
-(void)ZqqSendBlock:(ZqqSendBlock)block{
block([UIColor redColor]);
}
@end
//3.調(diào)用
ZqqTool *tool = [[ZqqTool alloc]init];
[tool zqqToolWithString:@"測試" andBlock:^(NSString *string) {
NSLog(@"%@",string);
}];
[tool ZqqSendBlock:^(UIColor *color) {
//
self.view.backgroundColor = color;
}];
注意:1渡讼、block中使用局部變量
局部變量在block中只讀。變量的值在Block外改變费薄,也不影響他在Block中的值硝全。局部變量加__block修飾可在block代碼塊內(nèi)被修改拐叉。
注意:2砸讳、block中循環(huán)引用問題
block用copy修飾家厌,在self持有block中調(diào)用self或調(diào)用屬于self的都會出現(xiàn)循環(huán)引用蹄咖!解決方法:__weak Class *weakSelf = self;
而block本身不被self持有扼劈,就不會出現(xiàn)循環(huán)引用了弹惦。例如:UIView的動畫block
[UIView animationWithDuration:0.2 animation:^{
//
}];