美文网首页
Block中嵌套block需要注意的事项

Block中嵌套block需要注意的事项

作者: 传说中的汽水枪 | 来源:发表于2019-01-16 11:43 被阅读3次

最近在看Blocks Programming TopicsBlocks有如下的这段话:

When you copy a block, any references to other blocks from within that block are copied if necessary—an entire tree may be copied (from the top). If you have block variables and you reference a block from within the block, that block will be copied.

大致翻译如下:

当你复制一个block的时候,在这个block里的其他block任何引用也会被复制,如果有必要的话,一颗完整的树也许被复制(从顶部开始)。如果你有block变量并且你在这个block引用了另一个block,另一个block也会被复制。

测试对象:RXBlockBlockObject

@interface RXBlockBlockObject : NSObject
- (void)test;
@end

RXBlockBlockObject.m文件中:

@interface RXBlockBlockObject()
@property (nonatomic, copy) int(^block)(int);
@property (nonatomic, assign) int tmpValue;
@end
@implementation RXBlockBlockObject
- (void)test
{
    [self _test_block_normal];
//    [self _test_block_nested_retain_cycle];
//    [self _test_block_nested];
}
- (void)dealloc
{
    NSLog(@"RXBlockBlockObject dellloc");
}
@end

测试类中:

- (void)_test_block
{
    RXBlockBlockObject *tmp = [RXBlockBlockObject new];
    [tmp test];
    // tmp 会被释放的
}

_test_block_normal method

- (void)_test_block_normal
{
    self.tmpValue = 10;
    self.block = ^(int m) {
        return m + 4;
    };
    void (^block1)(void) = ^{
        NSLog(@"%zd", self.block(5));
    };
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), block1);
}

持有关系如下描述:

self(viewController)持有了blockdispatch_after的一个全局管理器持有了block1block1持有了self,没有出现循环引用。

输出如下:

9
RXBlockBlockObject dellloc

_test_block_nested_retain_cycle method

- (void)_test_block_nested_retain_cycle
{
    self.tmpValue = 10;
    
    // A(self)强引用了B(block),B强引用了C(block1),C强引用了A(self)了,导致循环引用
    self.block = ^(int m) {
        // inline block
        
        void (^block1)(void) = ^{
            // 不会提示warning,但是实际上已经出现了循环引用
            NSLog(@"%zd", self.tmpValue + m);
            // 会提示warning: Capturing 'self' strongly in this block is likely to load to a retain cycle
            // 但是感觉这是无限递归调用了~~~~
            //            NSLog(@"%zd", self.block(10));
        };
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), block1);
        return m + 4;
    };
    
    void (^block2)(void) = ^{
        NSLog(@"%zd", self.block(5));
    };
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), block2);
}

持有关系如注释中的描述:

A(self)强引用了B(block),B强引用了C(block1),C强引用了A(self)了,导致循环引用。

输出结果是:

9
15

不会调用dealloc,出现循环引用,内存泄漏了

_test_block_nested method 上一个的进化版本,解决循环引用

- (void)_test_block_nested
{
    self.tmpValue = 10;
    __weak __typeof(self) weakSelf = self;
    self.block = ^(int m) {
        // inline block
        __strong __typeof(self) strongSelf = weakSelf;
        void (^block1)(void) = ^{
            NSLog(@"%zd", strongSelf.tmpValue + m);
        };
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), block1);
        return m + 4;
    };
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"%zd", self.block(5));
    });
}

使用__weak__strong解决,block2延长了self的生命周期
输出结果:

9
15
RXBlockBlockObject dellloc

相关文章

  • Block中嵌套block需要注意的事项

    最近在看Blocks Programming Topics中Blocks有如下的这段话: When you cop...

  • Block注意事项

    1.Block注意事项 在block内部可以访问block外部的变量 block内部也可以定义和block外部的同...

  • Block

    常用写法: OC中: Swift中: 注意事项: block默认存储在栈中,如果对block进行copy操作,bl...

  • 易忽略的循环引用

    1、嵌套循环引用 解决方案: 注意:建议嵌套Block时,block内部新声明一个方法,从而不会显得@weakif...

  • iOS block嵌套block中weakify的使用

    结论:嵌套中的block只需要写strongify,不需要再写一次weakify 只要持有block的变量和blo...

  • OC - Block

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

  • iOS 之 block(4.4)

    本章主题,讨论 block 的嵌套 总结:可以看出block 被捕获,有 BLOCK_FIELD_IS_BLOCK...

  • 解析 iOS 中的 Block

    1. OC中block的用法 iOS 中block被用于嵌套方法间传递,并在方法调用返回时,通过block回调返回...

  • block的一些注意事项

    Block的使用注意: block的内存管理(注意循环引用,默认在栈中(不需要内存管理),通过copy就在在堆中,...

  • 面试技巧攻克-iOS中对象间通信机制

    一、delegate和block 1、delegate和block的区别?block需要注意什么? delegat...

网友评论

      本文标题:Block中嵌套block需要注意的事项

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