美文网首页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