iOS中block的使用

作者: f1e583c455bf | 来源:发表于2017-04-21 15:38 被阅读244次

    一、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中block的使用

        本文链接:https://www.haomeiwen.com/subject/adplzttx.html