美文网首页
Block笔记(六)

Block笔记(六)

作者: MichealXXX | 来源:发表于2018-10-30 22:42 被阅读0次
Block循环引用

如果在block中使用附有__strong修饰符的对象类型自动变量,那么当Block从栈复制到堆时,该对象为Block所持有,这样容易引起循环引用

我们来看一下以下源码:

MyObject.h文件

#import <Foundation/Foundation.h>

typedef void(^blk_t)(NSString *myString);

@interface MyObject : NSObject

@property (nonatomic, copy)blk_t myBlock;

- (void)testBlock;

@end

MyObject.m文件

#import "MyObject.h"

@implementation MyObject

- (void)testBlock{
    self.myBlock(@"this is my block");
}

@end

Viewcontroller.m文件

#import "ViewController.h"
#import "MyObject.h"
@interface ViewController ()

@property(nonatomic,strong)NSString *vcString;

@property(nonatomic,strong)MyObject *obj;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.
    self.obj = [[MyObject alloc] init];
    self.obj.myBlock = ^(NSString *myString) {
        self.vcString = myString;
        NSLog(@"%@",self.vcString);
    };
    
    [self.obj testBlock];
}

我们首先创建了一个MyObject文件,在其.h文件中定义一个Block类型的属性,定义一个方法用于执行Block。然后我们在ViewController.m中使用这个MyObject类,在@interface部分定义一个NSString类型的字符串,以及MyObject类型对象obj。在viewDidLoad方法中初始化对象obj,并且为objBlock属性变量赋值,在Block语法内为ViewController定义的字符串赋值,最后执行obj对象的方法。

其结果正常执行,为NSString类型字符串赋值成功。

2018-10-30 21:40:37.271396+0800 test[4715:412296] this is my block

但是会有警告出现:

Capturing 'self' strongly in this block is likely to lead to a retain cycle

警告告诉我们这里可能会造成循环引用,那么造成的原因是什么呢?

首先我们在MyObject.h文件中定义了一个Block类型属性,也就是说MyObject类对象持有Block,我们又将MyObject对象定义在ViewController.m文件中的@interface区域,这时就相当于ViewController持有MyObject,当Block语法内使用self.vcString,并且由于Block语法赋值给了Block类型属性,因此通过Block语法生成在上的Block会复制到,并持有所使用的self,也就是像下面这种逻辑。

self->MyObject->Block->self

在之前的内存管理中说过,当两个对象互相持有对方强引用将会造成在作用域结束之后对象不能被正确释放,这就是循环引用

在内存管理中说道__weak修饰符可以解决循环引用的问题,在这里其实也是通过__weak修饰符解决,只不过方法不太一样,我们还是用上面的源码举例,只不过做一点点改变:

#import "ViewController.h"
#import "MyObject.h"
@interface ViewController ()

@property(nonatomic,strong)NSString *vcString;

@property(nonatomic,strong)MyObject *obj;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    __weak typeof(self) weakSelf = self;
    self.obj = [[MyObject alloc] init];
    self.obj.myBlock = ^(NSString *myString) {
        weakSelf.vcString = myString;
        NSLog(@"%@",weakSelf.vcString);
    };
    
    [self.obj testBlock];
}

可以看到这一段代码

__weak typeof(self) weakSelf = self;

self赋值给附有__weak修饰符的变量weakSelf,在Block语法中使用weakSelf,这样Block就不能持有self的强引用,也就打破了循环使用。

self->MyObject->Block --- self

总而言之,当我们在Block中使用self时,一定要注意是否会造成循环引用,根据情况添加__weak typeof(self) weakSelf

相关文章

  • Block笔记(六)

    Block循环引用 如果在block中使用附有__strong修饰符的对象类型自动变量,那么当Block从栈复制到...

  • Block常见使用总结(传值/作为参数/作为返回值等)

    来做个block的笔记。 block定义 block类型 block传值 block作为参数的方法定义与调用 bl...

  • iOS Block学习笔记(六) -- Block与__bloc

    我们看Block可以保存静态局部变量的地址, 通过这种方式修改静态局部变量的值, 如果是使用的自动变量, 为何不能...

  • runtime 之给 button 添加 block 事件支持

    这只是简单的笔记UIButton+block.h UIButton+block.m 使用

  • Day7 读书笔记&心得体会

    一、读书笔记回顾昨天的收获:什么是block、proc? block和proc是两种不同的东西, block有形无...

  • Objective-C的Block

    声明:本文是读了 做的笔记,以及结合本人写的例子总结的Block知识。 目录 Block入门什么是Block如何定...

  • __block和非__block

    自己的笔记: NSString *text = @"test"; testBlock block = ^{ dis...

  • Block 笔记

    Block表达式语法:^ 返回值类型 (参数列表) {表达式}声明Block类型变量语法:返回值类型 (^变量名)...

  • block笔记

    1.我在一个类中声明了一个block属性:a类 定义如下: 这里用的是weak修饰的,表示我不会将block从本身...

  • block(笔记)

    oc 里面的block:block确实是个很好用的东西,简单的来说就是做完一个事情后要干些什么,用了block就么...

网友评论

      本文标题:Block笔记(六)

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