美文网首页
关于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一些思考

    本质 一个block本质上就是一个函数指针,即那个代码快的内存地址;捕获上下文变量的内存块(结构体或者类) 定义 ...

  • 关于block的一些思考

    block简单来说就是一个回调,用来实现数据的方向传递,延时后的数据传递。但是block有一个比较让人头疼的地方,...

  • 关于Block的几点思考

    背景 block的问题算是老生常谈了,本以为对block很熟悉了,但是前几天跟同事聊到几个block的很有意思的点...

  • block底层实现

    最近读书,关于block的底层实现,有以下思考和总结 c++部分的相关步骤分析写在代码注释 一、block是什么 ...

  • 前端学习第二天 CSS层叠和属性

    1 关于 inline block inline-block的一些注意点: 是行内块标签 文字的高度 行高: in...

  • iOS面试之Block大全

    Block Block内容如下: 关于Block 截获变量 __block修饰符 Block的内存管理 Block...

  • iOS面试之Block模块

    Block Block内容如下: 关于Block 截获变量 __block修饰符 Block的内存管理 Block...

  • iOS-block3-__block变量的内存管理、__forw

    上文讲了一下__block的原理,但是关于__block还有一些其他东西,这篇文章就来慢慢讲述。 一. __blo...

  • 关于Block一些记录

    大概两三周前通过学习《Objective-C高级编程 iOS与OS X多线程和内存管理》中的Block章节,系统深...

  • iOS关于换肤和夜间模式的一些思考

    iOS关于换肤和夜间模式的一些思考 iOS关于换肤和夜间模式的一些思考

网友评论

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

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