OC中block的copy操作

block的copy操作

ARC环境下,编译器会根据情况自动地将栈内存上的block拷贝到堆内存上,以下几种情况编译器都会自动将栈上的block拷贝到堆内存

  • block作为函数返回值
  • 将block赋值给__strong修饰的强指针对象
  • block作为Cocoa API中方法名含有usingBlock的方法参数
  • block作为GCD API的方法参数

1、block作为函数的返回值时,代码如下:

typedef void(^MyBlock)(void);

MyBlock blockFun() {
    int a = 10;
    return ^{
        NSLog(@"%d", a); // 10
    };
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        MyBlock block = blockFun();
        
        // 执行block
        block();
        
        NSLog(@"%@", [block class]); // __NSMallocBlock__
    }
    return 0;
}

2、有强指针引用着block时,代码如下:

typedef void(^MyBlock)(void);

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        
        int a = 10;
        
        // 强指针block引用着^{NSLog(@"%d", a);}
        MyBlock block = ^{
            NSLog(@"%d", a); // 10
        };
        
        NSLog(@"%@", [block class]); // __NSMallocBlock__
        
        block();
        
        // 没有任何指针引用着^{NSLog(@"%d", a);}
        NSLog(@"%@", [^{
            NSLog(@"%d", a);
        } class]); // __NSStackBlock__
    }
    return 0;
}

3、block作为Cocoa API中方法名含有usingBlock的方法参数时,代码如下:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        
        NSArray *arr = @[@"1", @"2", @"3"];
        
        [arr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            NSLog(@"%@", obj);
        }];
    }
    return 0;
}

4、block作为GCD API的方法参数时,代码如下:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"111");
        });
    }
    return 0;
}

讲解示例代码Demo地址:https://github.com/guangqiang-liu/06.3-BlockDemo3

更多文章

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。