iOS开发总结-浅谈Block的内存管理

前言

对于大多数iOS开发人员来说,Block应该并不陌生,iOS4.0已开始支持Block,在编程过程中,Block被Objective-C看成是对象,它封装了一段代码,这段代码可以在任何时候执行。Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。它是对C语言的扩展,用来实现匿名函数的特性。
Block的使用很像函数指针,不过与函数最大的不同是:Block可以访问函数以外、词法作用域以内的外部变量的值。
Block的特殊特性方便了开发人员的使用,但是Block的内存需要开发人员自己管理,错误的内存管理会造成循环引用内存泄露,或者内存因为提前释放造成崩溃。
因此,Block的内存管理是很重要的,本文将主要讨论Block使用过程中的内存管理问题。


开发环境
  • Xcode 9正式版
  • ARC
  • 真机调试 iPhone 7 Plus 11.0.1
  • MacBook Pro 10.13

创建代码如下:

//局部变量
- (void)localVar
{
    int localVar = 10;
    NSLog(@"localVar --%p",&localVar);
    sumBlock block1 = ^(int x,int y){
        NSLog(@"localVar --%p",&localVar);
        return localVar + x + y;
    };
    localVar = 0;
    int z = block1(1,2);
    NSLog(@"localVar -- z = %d",z);
}
1.png

打印结果:

2.png
//静态变量
- (void)staticVar
{
    static int staticVar = 10;
    NSLog(@"staticVar --%p",&staticVar);
    sumBlock block2 = ^(int x,int y){
        NSLog(@"staticVar --%p",&staticVar);
        return staticVar + x + y;
    };
    staticVar = 0;
    int z = block2(1,2);
    NSLog(@"staticVar -- z = %d",z);
}
3.png

打印结果:

4.png
//全局变量
- (void)globalVar
{
    NSLog(@"globalVar --%p", &globalVar);
    sumBlock block3 = ^(int x, int y) {
        NSLog(@"globalVar --%p", &globalVar);
        return globalVar + x + y;
    };
    globalVar = 0;
    int z = block3(1, 2);
    NSLog(@"globalVar -- z = %d", z);
}
5.png

打印结果:


6.png
//__block
- (void)blockVar
{
    __block int blockVar = 10;
    NSLog(@"blockVar --%p", &blockVar);
    sumBlock block4 = ^(int x, int y) {
        NSLog(@"blockVar --%p", &blockVar);
        return blockVar + x + y;
    };
    blockVar = 0;
    int z = block4(1, 2);
    NSLog(@"blockVar -- z - %d", z);
}
7.png

打印结果:


8.png
总结
  1. block中的变量是静态或者全局类型时,在block中该变量的内存地址没有发生改变。由于静态变量和全局变量其地址是固定的,因此block在定义的时候并没有复制该变量的值,而是直接从其所在内存中读出。
  2. block中的变量是局部类型时,在block中它的地址都发生了变化,block在定义的时候拷贝了它(开辟了新的内存空间),它在block中是作为常量使用的,其值不受外面的影响。
  3. block中的变量是__block类型时,在block中它的地址都发生了变化,但是blockVar的值受到外界影响,这是因为blockVar在定义变量本身的时候是位于stack上的,而在定义block的时候,该变量并不是被复制了一份,而是编译器将其转移到了heap上,这个地方其实变量是被复制了一份的,并且作为生成的新的结构体的一个成员变量。这个是更深层次的东西,等研究关于__block的原理的东西的时候会有相关介绍。

参考相关资料

iOS开发总结-Block(二)
Block源码解析和深入理解
深入研究Block捕获外部变量和__block实现原理

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

推荐阅读更多精彩内容

  • 《Objective-C高级编程》这本书就讲了三个东西:自动引用计数、block、GCD,偏向于从原理上对这些内容...
    WeiHing阅读 9,872评论 10 69
  • 前言 Blocks是C语言的扩充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了这...
    小人不才阅读 3,785评论 0 23
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,908评论 25 708
  • 下午 草泥马你麻痹还是不明白匝数比和反馈系数草泥马啊 高频实验狗电路图日你哥mutlisim仿真不出结果我勒个槽 ...
    陆海光和阅读 228评论 0 0
  • 《四书章句集注》:愠,纡问反。愠,含怒意。君子,成德之名。尹氏曰:“学在己,知不知在人,何愠之有。”程子曰:“虽乐...
    bodhi1984阅读 2,245评论 0 0