Block

基本原理

  • Objective-C 是对C 语言的扩展,block的实现是基于指针和函数指针
  • 代码输入 inlineBlock 就会出再一段block代码,类似于init
block 的创建
void(^blockName)(NSString *) = ^(NSString *param) { NSLog(@"%@",param); }; blockName(@"hello"); //声明 返回值类型(^block名称)(参数列表) void(^Block1)( ); //实现 block = ^(参数列表){ 代码块 } Block1 = ^( ){NSLog(@"我的代码块"); } //调用 block名称(参数列表) Block( );

block 作属性参数使用
@property (nonatomic, copy) void(^blockName)(NSString *); //一般用 tyedef tyedef NSString(^Block2 )(NSString *, NSString *)

block 做方法参数使用
void(^Block2)(int,int) = ^(int a, int b){ NSLog(@"我的第二个代码块"); } [self method:block2];

-(void)method:(void(^)(int,int))block{ block(10,20) }

Tips
- (void)viewDidLoad { [super viewDidLoad]; int a = 3; void (^ block)() = ^{ NSLog(@"%d",a); }; a = 5; block(); } ———————————————————————————————————— 情况2: - (void)viewDidLoad { [super viewDidLoad]; static int a = 3; ***区别点:静态变量*** void (^ block)() = ^{ NSLog(@"%d",a); }; a = 5; block(); } ———————————————————————————————————— 情况3: - (void)viewDidLoad { [super viewDidLoad]; __block int a = 3; ***区别点:被__block修饰*** void (^ block)() = ^{ NSLog(@"%d",a); }; a = 5; block(); } ———————————————————————————————————— 情况4: __block int a = 3; ***区别点:全局变量***- (void)viewDidLoad { [super viewDidLoad]; void (^ block)() = ^{ NSLog(@"%d",a); }; a = 5; block(); }//局部变量,block传值(值拷贝); //静态变量,全局变量,__block修饰,blokc传址(址拷贝);

循环引用
一般我们为避免block中相互持有而造成谁都无法释放,引起循环引用,从而造成内存泄露,所以需要typeof(self)[1]
__weak typeof(self)weakSelf = self; //推荐写法 __weak __typeof(self)weakSelf = self; __weak XXViewController *weakSelf = self; __weak id weakSelf = self; __weak __typeof(&*self)weakSelf = self; //当然也可以写成宏定义 #define WF(weakSelf)__weak typeof(self) weakSelf = self;

NSString str = @"测试1"; typeof(a) b = @"测试2"; typeof(a) 表示得到对象a的类型

【Block】但有些情况可以直接使用self
  • 调用系统方法:
//block虽然对self 强引用,但self不持有这个静态方法 [UIView animateWithDuration:0.5 animations:^{ NSLog(@"%@",self); }];

  • block 不是self 的属性
//self不持有这个block,所以也不存在循环引用 void(^block)(void) = ^(){ NSLog("%@",self); }

Block 与 Delegate
两者非常类似,用法也相近,比如我们自定义一个UITableViewCell,cell上显示文字信息和一个请情Button,点击button后push到下一个页面。但cell 没有能力实现 push 功能,因为只能是
[self.navigationController pushViewController:VC];
  • 如果用代理的话,Cell 需要制定协议,设置代理,委托代理实现 push 功能
//设置协议 @protocol CustomCellDelegate - (void)pushToNewPage; @end@interface CustomTableViewCell : UITableViewCell @property(nonatomic, assign) id delegate; @property (nonatomic, strong) UILabel *text1Label; @property(nonatomic,strong) UIButton *detailBtn; @end

//在cell的.m文件中给Button添加方法 [self.detailBtn addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside]; //对应的btnClicked方法 - (void)btnClicked:(UIButton *)btn{ //最好做这种安全判断 if (self.delegate && [self.delegaterespondsToSelector:@selector(pushToNewPage)]) {[self.delegate pushToNewPage]; } }

//在ViewController的.m文件中遵守协议 @interface ViewController () @end//设置代理 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ ···· //很重要 cell.delegate = self; return cell; }

//实现协议方法 - (void)pushToNewPage{DetailViewController*detailVC = [[DetailViewController alloc] init]; [self.navigationController pushViewController:detailVC animated:YES]; }

  • 如果用Block的,不需要制定协议
@interface CustomTableViewCell : UITableViewCell //直接定义一个block @property (nonatomic, copy) void (^ButtonBlock)(); @property (nonatomic, strong) UILabel *text1Label; @property(nonatomic,strong) UIButton *detailBtn; @end

//在cell的.m文件中给Button添加方法 [self.detailBtn addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside]; //对应的btnClicked方法 -(void)btnClicked:(UIButton *)btn{ //最好做这种安全判断 if (ButtonBlock) { ButtonBlock( ) } }

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ ···· //很重要 cell.ButtonBlock = ^{ [self pushToNewPage]; }

参考文档
  1. typeof(a) 和 __typeof(a) 都可以,但 可能是苹果比较推荐前者 ?

    推荐阅读