美文网首页
对于block和静态变量的思考

对于block和静态变量的思考

作者: 无神 | 来源:发表于2018-04-09 11:19 被阅读61次

最近的面试中,被问到各种各样的问题,有的问题真的是一脸懵逼。Block的调用,有的时候回产生循环引用,与及如何解除循环引用,做iOS开发的,想必大家都知道。然而最近被问到这样一个问题,在block内部申明使用static变量,会造成循环引用吗?第一反应是,自己没有这么做过,也没有见别人这样写过,哪怕是开源的框架里,目前也没有这么写的。于是和小伙伴们讨论了一下,也敲代码验证了一下。

循环引用是什么?

当两个不同的对象各有一个强引用指向对方,那么循环引用变产生了,当然一个对象产生的环也是一样的。

从引用计数来说,如果两个对象互相引用的时候,双方的引用计数都是+1的,导致如何时候引用计数都不为0,始终无法释放他们的内存,即使已经没有变量持有它。

static变量

static关键字声明的变量必须放在implementation外面,或者方法中,如果不为它赋值默认为0,它只在程序开机初始化一次。

先得说下内存中和变量有关的分区:堆、栈、静态区。其中,栈和静态区是操作系统自己管理的,对程序员来说相对透明,所以,一般我们只需要关注堆的内存分配,而循环引用的产生,也和其息息相关,即循环引用会导致堆里的内存无法正常回收。

代码分析如下

- (void)testBlockWithStaticVariable {
    
    static NSInteger num1 = 100;
    __block NSInteger num2 = 5;
    void (^block)(void) = ^{
      
        static NSInteger num3 = 10;
        NSInteger num4 = 0;
        NSLog(@"the current value is num1 = %@, num2 = %@, num3 = %@, num4 = %@",@(num1++),@(num2++),@(num3++),@(num4++));
        //[self testRecycle]; //可以正常调用,不会发生循环引用
    };
    for(NSInteger i = 0; i < 10; i++){
        
        block();
    }
}
block内部申明static变量

从结果看num1、num2、num3都进行了累加操作,只有内部申请的普通变量num4没有进行叠加,因为它是放在栈上的,每次都初始化。num1、num3都是static的,无论是在block内部调用外部的static变量,还是在block内部申请使用static变量,都不造成循环引用,也不会发生内存泄漏。
在block内部调用当前类的方法,不会发生循环引用。

- (void)testRecycle {
    
    static NSInteger num1 = 100;
    __block NSInteger num2 = 5;
    self.testBlock = ^{
        
        static NSInteger num3 = 10;
        NSInteger num4 = 0;
        NSLog(@"the current value is num1 = %@, num2 = %@, num3 = %@, num4 = %@",@(num1++),@(num2++),@(num3++),@(num4++));
        NSLog(@"----------------");
        //[self testBlockWithStaticVariable]; //会发生循环引用 Capturing 'self' strongly in this block is likely to lead to a retain cycle
    };
    for(NSInteger i = 0; i < 10; i++){
        
        self.testBlock();
    }
}

打印结果和上图一样,唯一不同的是,在该block内部调用当前类的方法,系统会报Capturing 'self' strongly in this block is likely to lead to a retain cycle的错误。

总结

block内部申明static变量,不会内存泄露,也不会循环引用。

相关文章

  • 对于block和静态变量的思考

    最近的面试中,被问到各种各样的问题,有的问题真的是一脸懵逼。Block的调用,有的时候回产生循环引用,与及如何解除...

  • 聊聊OC中的Block

    对于block中的全局变量和静态变量,block中改变量的地址不发生变化;对于一般变量,block中会对此变量进行...

  • __block修饰符

    __block用于解决block内部不能修改auto变量值的问题__block不能修饰全局变量和静态变量?编译器会...

  • block

    一篇文章看懂iOS代码块Block - 简书 在Block中可以访问局部变量 Block内访问全局变量和静态变量 ...

  • 什么时候使用静态变量和方法

    静态方法和静态变量在调用时非常方便,使用类名.的方式就可以调用。那什么时候该使用静态变量和静态方法呢? 静态变量在...

  • Objective-C添加类属性

    先回顾一下静态变量与全局变量的一些知识。 头文件中定义全局变量和静态变量的区别。 源文件中定义全局变量和静态变量的...

  • Java类

    总结一下执行流程就是: 父类静态变量和静态代码块; 子类静态变量和静态代码块; 父类普通成员变量和普通代码块; 父...

  • 关于block的所有问题

    关于block捕获外部的变量 (1)局部变量(2)静态变量(3)全局变量(4)全局静态变量(6)block捕获外边...

  • java代码的执行顺序

    若类还未被加载 先执行父类的静态代码块和静态变量初始化,并且静态代码块和静态变量的执行顺序只跟代码中出现的顺序有关...

  • iOS面试题:Block变量的截获

    block如果要访问block以外定义的变量,对基本数据类型的局部变量、静态变量、全局变量、全局静态变量和对象变量...

网友评论

      本文标题:对于block和静态变量的思考

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