iOS中block的使用

96
勤劳的小QQ
2017.04.21 15:38* 字数 553

一、block简介

block代码块是在iOS4开始引入的对C语言的扩展,用来实现匿名函数的特性,block是一种特殊的数据类型,其可以正常定义变量、作为参数、作为返回值,blcok还可以保存一段代码,在需要时调用。

二、block定义

block在定义时并不会执行内部的代码,只有在调用时才会执行。

//block变量的赋值:Block变量 = ^(参数列表){函数体};

1、无参数无返回值的block

//1、无参数无返回值的block
    //zqqBlock是block名 无参数可省略参数列表()
    //void (^zqqBlock)() = ^{};
    void (^zqqBlock)() = ^(){
        NSLog(@"这是无返回值无参数的block");
    };
    //调用
    zqqBlock();

2、有参数无返回值的block

    //zqqBlock是block名 NSString 是参数类型,x,y参数
    void (^zqqBlock)(NSString* ,NSString*) = ^(NSString *x,NSString *y){
        NSLog(@"这是无返回值有参数的block,参数是%@,%@",x,y);
    };
    //调用
    zqqBlock(@"a",@"b");

3、有参数有返回值的block

    //NSString是返回类型 zqqBlock是block名 NSString 是参数类型,x,y参数
    NSString* (^zqqBlock)(NSString* ,NSString*) = ^(NSString *x,NSString *y){
        return [NSString stringWithFormat:@"%@+%@",x,y];
    };
    //调用
    NSString *testStr = zqqBlock(@"a",@"b");
    NSLog(@"%@",testStr);

三、block使用

1、block重命名

利用typedef为block进行重命名

#import "ViewController.h"
@interface ViewController ()
//定义一个无返回值无参数的block
typedef void (^zqqBlock)();
//用自定义的zqqBlock声明一个block
@property (nonatomic, copy) zqqBlock abock;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 避免循环引用,用__weak修饰
    __weak ViewController *weakSelf = self;
    self.abock = ^{
        weakSelf.view.backgroundColor = [UIColor redColor];
    };
    //调用
    self.abock();
}
@end

2、block的应用场景

block声明属性要用copy修饰
因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的
<栈 :由系统维护的局部变量 是存在栈上的,其生命周期随函数的生命周期>
<堆 :由程序员申请空间地址,由程序员手动释放,生命周期受到程序员控制>
使用retain也可以,因为block的retain行为默认是用copy的行为实现的,block变量默认是声明为栈变量的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的操作一致,最好声明为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时调用
    NextViewController *nextVc = [[NextViewController alloc]init];
    [self.navigationController pushViewController:nextVc animated:YES];
    //调用block
    __weak ViewController *weakSelf = self;
 //block的回调只对最后一次赋值有效
    nextVc.popToNextBlock = ^(UIColor *color){
        //避免循环引用,应该使用弱引用
          weakSelf.view.backgroundColor = color;
    };
  • 在方法中定义block 回调传值
//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.调用
    ZqqTool *tool = [[ZqqTool alloc]init];
    [tool zqqToolWithString:@"测试" andBlock:^(NSString *string) {
        NSLog(@"%@",string);
    }];
  • 作为参数传递
//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.调用
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代码块内被修改。

注意:2、block中循环引用问题

block用copy修饰,在self持有block中调用self或调用属于self的都会出现循环引用!解决方法:__weak Class *weakSelf = self;
而block本身不被self持有,就不会出现循环引用了。例如:UIView的动画block

[UIView animationWithDuration:0.2 animation:^{
     //
}];
iOS开发基础知识
Web note ad 1