美文网首页
关于block的一些思考

关于block的一些思考

作者: Rokkia | 来源:发表于2018-07-02 09:25 被阅读20次

    block简单来说就是一个回调,用来实现数据的方向传递,延时后的数据传递。
    但是block有一个比较让人头疼的地方,就是block内self的使用。
    先看一下block内部结构

    让我们写一个会循环引用的情况
    RokkiaBlockTest.m内

    typedef void(^HAHA)(NSInteger a);    //定义block
    
    @interface RokkiaBlockTest()
    @property(nonatomic, assign)NSInteger inte;  //定义block中会用到的参数
    @property(nonatomic, copy)HAHA h;      //在property中定义block
    @end
    
    @implementation RokkiaBlockTest
    -(void)blockblockblock{
        // __weak __typeof(self) wself = self;
        self.h = ^(NSInteger a){
            NSLog(@"%ld", a + self.inte);
        };
        self.h(20);
    }
    -(void)dealloc{
        NSLog(@"程序结束");
    }
    @end
    

    ViewController.m内

    #import "RokkiaBlockTest.h"
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        RokkiaBlockTest *network = [[RokkiaBlockTest alloc]init];    
        [network blockblockblock];
    }
    

    我们运行程序,我们会发现dealloc中的程序结束并没有执行。
    原因,我们回到这里

    self.h = ^(NSInteger a){      //self持有了block OK block计数器+1 
        NSLog(@"%ld", a + self.inte);  //block内 block持有了self OK self计数器+1
    };
    self.h(20);  //执行,
    

    问题来了因为block与self计数器都 + 1了 当程序结束后 self - 1 block - 1 但是self-1并不等于0 于是self不会被释放 block同理,于是他们互相持有却没有一个可以先释放,于是形成循环引用。

    解决方式:

    -(void)blockblockblock{
        __weak __typeof(self) wself = self;   // 在block外对self进行weak操作
        self.h = ^(NSInteger a){
            NSLog(@"%ld", a + self.inte);
        };
        self.h(20);
    }
    

    问题来了,如果self没有持有block 或者 block没有持有self的情况会怎么样。
    改写1

    -(void)blockblockblock{
        // __weak __typeof(self) wself = self;
        self.h = ^(NSInteger a){
            NSLog(@"%ld", a);   // 去掉self
        };
        self.h(20);
    }
    

    改写2

    -(void)blockblockblock{
        // __weak __typeof(self) wself = self;
        HAHA h = ^(NSInteger a){
            NSLog(@"%ld", a);
        };
        h(20);
    }
    

    结果

    2018-06-27 13:56:56.634307+0800 RokkiaBlockTest[11935:1371001] 程序结束
    

    这里有另外一个问题了,如果将一个block传入到单例中会怎样。
    单例对象 TTest.h中

    typedef void(^doSome)(NSInteger a);
    @interface test : NSObject
    +(nonnull instancetype) sharedManager;
    -(void)doSomeWithBlock:(doSome _Nullable )block;
    @end
    

    单例对象TTest.m中

    @implementation test
    +(nonnull instancetype)sharedManager{
        static id instance;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            instance = [self new];
        });
        return instance;
    }
    -(void)doSomeWithBlock:(doSome)block{
        block(20);
    }
    @end
    

    RokkiaBlockTest.m中

    -(void)testtest{
        [self dododo];
        TTest *t = [TTest sharedManager];
        if (self.ds) {
            [t doSomeWithBlock:self.ds];
        }else{
            NSLog(@"没有执行");
        }
    }
    
    -(void)dododo{
    //    __weak __typeof(self) wself = self;
        self.ds = ^(NSInteger a){
            NSLog(@"test %ld",a + self.inte);
        };
    }
    

    Viewcontroller.m中

    [network testtest];
    

    结果

    2018-06-27 14:13:41.195511+0800 RokkiaNetWorking[12090:1385836] test 30
    

    我们发现产生了循环引用
    解决,跟上面一样 添加 __weak __typeof(self) sweak = self;
    跟上面的一样思考, 如果self没有持有block 或者 block没有持有self的情况会怎么样。
    改写1

    -(void)testtest{
        test *t = [test sharedManager];
        doSome ds = ^(NSInteger a){
            NSLog(@"test %ld",a + self.inte);
        };
        [t doSomeWithBlock:ds];
    }
    

    改写2

    -(void)testtest{
        [self dododo];
        test *t = [test sharedManager];
        if (self.ds) {
            [t doSomeWithBlock:ds];
        }else{
            NSLog(@"没有执行");
        }
    }
    
    -(void)dododo{
        // __weak __typeof(self) wself = self;
        self.ds = ^(NSInteger a){
            NSLog(@"test %ld",a);
        };
    }
    

    结果

    2018-06-27 14:19:17.832694+0800 RokkiaNetWorking[12118:1389889] test 30
    2018-06-27 14:19:17.833403+0800 RokkiaNetWorking[12118:1389889] 程序结束
    

    相关文章

      网友评论

          本文标题:关于block的一些思考

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