美文网首页iOS 开发IOS知识整理iOS 开发
Block从入门到放弃宝典(二):循环引用

Block从入门到放弃宝典(二):循环引用

作者: 键盘风筝 | 来源:发表于2016-10-11 17:24 被阅读552次

    十一大家去哪happy了,不过去哪都是开启看人模式,这是block的第二篇文章,给大家简单剖析一些循环引用的问题,大家下一篇想看什么可以给楼主留言或私信,都会满足大家的

    其实block是个双面剑,用好了可以使代码更简洁,增加可读性,但是往往大家忽略了循环引用的问题,所以还是希望大家要知其一,更要知其二,本着实用性为主,还是从实际项目中给大家介绍几个经典的循环引用场景.

    怎么造成循环引用

    两个对象相互持有,谁也不释放谁,就造成循环应用了

    循环引用.jpeg

    循环引用场景(一)

    typedef void(^block)();
    
    @interface ViewController ()
    @property (copy, nonatomic) block testBlock;
    @property (copy, nonatomic) NSString *testString;
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self. testBlock = ^(){
            NSString *str = self.blockString;
        };    
    }
    
    
    如何造成循环引用

    这样会造成循环引用,因为self.testBlock和self.blockString互相都是强引用,导致互相都不释放,我画出两者的关系


    循环引用场景一.png
    解决方法
    - (void)viewDidLoad {
        [super viewDidLoad];
        __weak typeof(self) weakSelf = self;
        self. testBlock = ^(){
            NSString *str = weakSelf.blockString;
        };    
    }
    

    原理:使用__weak来修饰self对象,使其在block中不被持有,破坏循环引用


    打破循环引用.png

    循环引用场景(二)

    大家在使用网络请求的时候,经常会用到block,但是殊不知也有可能已经循环引用了
    首先创建一个NetWorkTool,并写一个方法

    @interface NetWorkTools : NSObject
    -(void)netWorkWithUrl:(void(^)(NSString *urlStr))urlStr;
    @end
    
    @interface NetWorkTools ()
    @property (nonatomic, copy) void (^finishedBlock)(NSString *);
    @end
    
    -(void)netWorkWithUrl:(void(^)(NSString *urlStr))urlStr{
        // 1. 使用属性记录 block
        self.finishedBlock = urlStr;
    }
    
    

    在ViewController来调用这个类

    @interface SecViewController ()
    @property(nonatomic,strong)NetWorkTools *tool;
    @end
    - (void)viewDidLoad {
        [super viewDidLoad];
        NetWorkTools *tool = [[NetWorkTools alloc] init];
        self.tool = tool;
        [self.tool netWorkWithUrl:^(NSString *urlStr) {
            self.view.backgroundColor = [UIColor whiteColor];
        }];
    }
    
    如何造成循环引用
    循环引用场景2.png
    解决方法
    @interface SecViewController ()
    @property(nonatomic,strong)NetWorkTools *tool;
    @end
    - (void)viewDidLoad {
        [super viewDidLoad];
        __weak typeof(self) weakSelf = self;
        NetWorkTools *tool = [[NetWorkTools alloc] init];
        self.tool = tool;
        [self.tool netWorkWithUrl:^(NSString *urlStr) {
            weakSelf.view.backgroundColor = [UIColor whiteColor];
        }];
    }
    

    写在最后

    其实有的时候并没有造成循环引用,举个例子

    //这个是GCD的延迟调用方法,并没有造成循环引用
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            self.view.backgroundColor = [UIColor whiteColor];
        });
    

    所以分析是不是循环引用还是多在项目中实践,坑踩得多了自然就懂了,虽然我这个方法很不可取

    附上demo地址

    相关文章

      网友评论

      • 马爷:block 其实引起循环引用的例子其实相对不对 我觉得只要避免在你强引用别的 block 的时候 如果有调用自己当前内部的东西 这样的基本上都是循环引用 其他的应该差不多都形成不了 所有说 我还是建议说说这个1。什么是强引用?2.什么是弱引用?为什么block内部调用self就会出现循环引用?
        键盘风筝:@马爷 嗯,是的,还是有点偏向项目使用,没有把基础讲明白
      • 朋友有朋:表示有几个地方,比较模糊1。什么是强引用?2.什么是弱引用?为什么block内部调用self就会出现循环引用?
        键盘风筝:@朋友有朋 嗯,本来想解释一下强弱引用,但是太基础没有说明,以后会针对强弱引用写一篇文章,第三个问题可以看我画的图
      • 巴图鲁:不错
        键盘风筝:@巴图鲁 谢谢:heart_eyes:

      本文标题:Block从入门到放弃宝典(二):循环引用

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