美文网首页
如何正确的使用Block

如何正确的使用Block

作者: Mr姜饼 | 来源:发表于2018-07-26 15:01 被阅读0次

循环引用(原理)

1.给大家简单的概括一下循环引用出现的原理

A持有B  但是B又强引用A,而A在销毁的时候,就出现了所谓的循环引用

case1:

//ClassA:

@protocol ClssADelegate

- (void)fuck;

@end

@interface ClassA : UIViewController

@property (nonatomic, strong) id delegate;

@end

//ClassB:

@interface ClassB ()

@property (nonatomic, strong) ClassA *classA;

@end

@implementation ClassB

- (void)viewDidLoad {

    [super viewDidLoad]; 

    self.classA = [[ClassA alloc] init];  

    self.classA.delegate = self;

}

简单分析上面的例子:

B持有A属性,A的delegate强引用了A,这样就会导致循环引用

解决的最好办法就是

将@property (nonatomic, strong) id delegate;

改成:

@property (nonatomic, weak) id delegate;

case 2:

@interface ClassA ()

@property (nonatomic, copy) dispatch_block_t block;

@property (nonatomic, assign) NSInteger tem;

@end

@implementation ClassA

- (void)viewDidLoad {

    [super viewDidLoad];

    self.block = ^{

        self.tem = 1;

    };  

}

self持有block,而堆上的block又会持有self,所以会导致循环引用

修改方法:

 __weak typeof(self) weakSelf = self

    self.block = ^{

        weakSelf.tem = 1;

    };  

结论

如上delegate和block引起的循环引用的处理方式,有一个共同的特点,就是使用weak(弱引用)来打破环,使环消失了。所以,可以得出结论,我们可以通过使用将strong(强引用)用weak(弱引用)代替来解决循环引用。




进一步学习 深处探讨

//ClassB是一个UIViewController,假设从ClassA pushViewController将ClassB展示出来

@interface ClassB ()

@property (nonatomic, copy) dispatch_block_t block;

@property (nonatomic, strong) NSString *str;

@end

@implementation ClassB

- (void)dealloc {

}

- (void)viewDidLoad {

    [super viewDidLoad];

    self.str = @"111";

    __weak typeof(self) weakSelf = self;

    self.block = ^{

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

            NSLog(@"%@", weakSelf.str);

        });

    };

    self.block();   

}

这里会有两种情况:

若从A push到B,10s之内没有pop回A的话,B中block会执行打印出来111。

若从A push到B,10s之内pop回A的话,B会立即执行dealloc,从而导致B中block打印出(null)。这种情况就是使用weakSelf的缺陷,可能会导致内存提前回收。

2、weakSelf和strongSelf

@interface ClassB ()

@property (nonatomic, copy) dispatch_block_t block;

@property (nonatomic, strong) NSString *str;

@end

@implementation ClassB

- (void)dealloc {

}

- (void)viewDidLoad {

    [super viewDidLoad];

    self.str = @"111";

    __weak typeof(self) weakSelf = self;

    self.block = ^{

        __strong typeof(self) strongSelf = weakSelf;

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

            NSLog(@"%@", strongSelf.str);

        });

    };

    self.block();   

}

我们发现这样确实解决了问题,但是可能会有两个不理解的点。

这么做和直接用self有什么区别,为什么不会有循环引用:外部的weakSelf是为了打破环,从而使得没有循环引用,而内部的strongSelf仅仅是个局部变量,存在栈中,会在block执行结束后回收,不会再造成循环引用。

这么做和使用weakSelf有什么区别:唯一的区别就是多了一个strongSelf,而这里的strongSelf会使ClassB的对象引用计数+1,使得ClassB pop到A的时候,并不会执行dealloc,因为引用计数还不为0,strongSelf仍持有ClassB,而在block执行完,局部的strongSelf才会回收,此时ClassB dealloc。

这样做其实已经可以解决所有问题,但是强迫症的我们依然能找到它的缺陷:

block内部必须使用strongSelf,很麻烦,不如直接使用self简便。

很容易在block内部不小心使用了self,这样还是会引起循环引用,这种错误很难发觉。

相关文章

  • 如何正确的使用Block

    循环引用(原理) 1.给大家简单的概括一下循环引用出现的原理 A持有B 但是B又强引用A,而A在销毁的时候,就出现...

  • 白话block

    本文内容 什么是block? block的用途 block的用法 block在使用中遇到的问题 如何使用xcode...

  • iOS程序crash的几种情况

    调用block时没有判断Block是否为空 如果block为nil,直接调用会crash 正确的使用方法是先判断b...

  • block本质

    探究block本质fishhookHook Objective-C Block with Libffi如何使用li...

  • css div盒子居中的方法

    如何让盒子居中? 1、block元素,使用margin属性 2、block元素,在flex容器上使用justify...

  • Block简介和在GCD中的举例

    Block简介 Block的使用 1 如何用block实现 hello world!!! 解释一下上面那段东西时鬼...

  • 关于block嵌套定义导致的内存泄漏

    block的使用极大方便了我们的开发,但是不正确的使用block时就会导致意想不到的问题。[toc] 1. 单层b...

  • 重新认识 Block

    1、如何声明一个Block 使用^操作符来来声明一个block变量和指示block文本的开始。Block本身的主 ...

  • OC - Block

    导读: 一、Block是什么 二、Block的特点和作用 三、Block的声明、定义及注意事项 四、如何使用Blo...

  • [译]《Motion Design for iOS》(二十三)

    你可能会想,我们使用基于block的UIView动画时并不需要处理这些,完全正确。UIView上基于block的动...

网友评论

      本文标题:如何正确的使用Block

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