block 中使用__weak 和__strong修饰符的问题

在ARC环境下,我们常常会使用weak 的修饰符来修饰一个变量,防止其在block中被循环引用,但是有些特殊情况下,我们在block中又使用strong 来修饰这个在block外刚刚用__weak修饰的变量,为什么会有这样奇怪的写法呢?

后来上网查资料,给的解释就是下面的这段话:

    在block中调用self会引起循环引用,但是在block中需要对weakSelf进行
strong,保证代码在执行到block中,self不会被释放,当block执行完后,
会自动释放该strongSelf;

对于程序员来说,文字说明要有,编码就更少不了了;下面是我对上面的话转译成的代码;

第一步:我们自定义一个类,在该类dealloc方法中加一行打印语句;

@interface sampleObject :NSObject

@end

@implementation sampleObject

- (void)dealloc{
       NSLog(@"dealloc %@",[self class]);
}

@end   

第二步:实例化该类,并在block中调用它;(没有加strong修饰符,三秒后在另一个异步线程中释放该对象)

sampleObject *sample = [[SampleObject alloc]init];
self.sample= sample;

__weakSampleObject* weaksample = self->sample;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
    NSIntegercount =0;
    //__strong SampleObject* strongsample = weaksample;

    while(count<10) {
        count++;
        NSLog(@"aaa %@",weaksample);
        sleep(1);
    }
});

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3*NSEC_PER_SEC)),dispatch_get_main_queue(), ^{
    self.sample  =nil;
}); 

打印结果如下(没有用strong修饰符的打印结果如下):

结论是:如果仅仅使用__weak去修饰变量,当别处把变量释放后,block中该变量也会被释放掉

那么好,我们在把第二步中的方法修改一下,加上strong修饰符:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
    __strongSampleObject* strongsample = weaksample;
    NSIntegercount =0;
    while(count<10) {
        count++;
        NSLog(@"aaa %@",strongsample);
        sleep(1);
    }
});

打印结果如下:

结论是当加上修饰符strong时,当别处把变量释放掉,但调用该变量的block如果仍然没有执行结束,那么系统就会等待block执行完成后再释放,对该变量在block中的使用起到了保护作用。当block执行结束后会自动释放掉。

文/__骨头__(简书作者)
原文链接:http://www.jianshu.com/p/bb63aabdb2db
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

时间: 2024-11-05 14:34:30

block 中使用__weak 和__strong修饰符的问题的相关文章

C++中 容易忽视的const 修饰符

C++可以用const定义常量,也可以用#define定义常量,但是前者比后者有更多的有点: (1)const常量有数据类型,而宏常量没有数据类型.编译器可以对const进行类型安全检查,而后者只进行字符替换,没有类型安全检查,并且在字符替换中可能会产生意料不到的错误!(如类型不匹配问题) (2)编译器处理方式不同.define宏是在预处理阶段展开,const常量是编译运行阶段使用. (3)存储方式不同.define宏仅仅是展开,有很多地方使用,就展开多少次,不会分配内存.const常量会在内存

文成小盆友python-num8 面向对象中的成员,成员修饰符,特殊成员,异常处理,设计模式之单例模式

本节主要内容: 1.面向对象中的成员 2.成员修饰符 3.特殊成员 4.异常处理 5.设计模式之单例模式 一.面向对象中的成员(类的成员) 类的成员总共可以分为3大类,每类中有不同的分支. 1.总述,基本分类 如下图所示: 类成员包括字段,方法,和属性 2.字段 如上图字段分为普通字段和静态字段,两者的使用有区别,但是最大的区别在于两者在内存中的保存位置有区别. 普通字段属于对象而静态字段属于类,在使用过程中谁的字段就由谁来调用. 静态字段和普通字段的定义如下: 在调用时分各自调用 #####类

__strong修饰符

本文用来观察,对于__strong修饰符,编译器为我们自动添加了什么代码,这些代码对于引用计数有什么影响. 例子一 X __strong *x1 = [[X alloc] init]; 使用控制台打印引用计数,计数值为1,符合预期: (lldb) p CFGetRetainCount((__bridge CFTypeRef)x1) (CFIndex) $0 = 1 (lldb) 例子二 X __strong *x2 = [X create]; //create返回对象X 使用控制台查看引用计数,

__weak与__block修饰符区别

API Reference对__block变量修饰符的解释,大概意思: 1.__block对象在block中是可以被修改.重新赋值的. 2.__block对象在block中不会被block强引用一次,从而不会出现循环引用问题. API Reference对__weak变量修饰符的解释,大概意思: 使用了__weak修饰符的对象,作用等同于定义为weak的property.自然不会导致循环引用问题,因为苹果文档已经说的很清楚,当原对象没有任何强引用的时候,弱引用指针也会被设置为nil. 因此,__

__weak与__block修饰符到底有什么区别

API Reference对__block变量修饰符有如下几处解释: //A powerful feature of blocks is that they can modify variables in the same lexical scope. You signal that a block can modify a variable using the __block storage type modifier. //At function level are __block vari

__strong 修饰符

__strong 是id类型和所有对象类型默认的所有权修饰符 __strong 表示对对象的强引用,在ARC中持有强引用变量在超出其作用域或强引用失效(如被置为nil),则引用对象被自动释放 id __strong obj1=[[NSObject alloc] init]; /* create object A */ /* * obj1持有对对象A的强引用 */ id __strong obj2=[[NSObject alloc] init]; /* create object B*/ /* *

C#中的overrid和new修饰符区别(代码)

在C#的继承中尝尝会用到相关的修饰词:override和new.这两个修饰符都可以在新的子类中,重写同名的父类方法. override: 扩展或修改继承的方法.属性.索引器或事件的抽象或虚拟实现需要使用到. new:在用作声明修饰符时,new 关键字可以显式隐藏从基类继承的成员. 隐藏继承的成员时,该成员的派生版本将替换基类版本. 以上是这两个修饰符的解释.对于这两者之间的区别之类的说法,其实网上找到的有很多,大多都是些概念性的东西.我这里主要是对于,自己测试的代码和大家分享下. 1 using

解析Visual C# 7.2中的private protected访问修饰符

去年12月份,随着Visual Studio 2017 Update 15.5的发布,Visual C#迎来了它的最新版本:7.2. 在这个版本中,有个让人难以理解的新特性,就是private protected访问修饰符(Access Modifier).至此,C#语言的访问修饰符有以下几种: private protected public internal internal protected private protected 既然有了private和protected,那么privat

vue中常用的事件和修饰符简单总结

1:阻止冒泡事件 JS事件流其中一种是冒泡事件,当一个元素被触发一个事件时,该目标元素的事件会优先被执行,然后向外传播到每个祖先元素,恰如水里的一个泡泡似的,从产生就一直往上浮,到在水平面时,它才消失.在这个过程中,如果你只希望事件发生在目标元素,而不想它传播到祖先元素上去,那么你需要在"泡泡"离开对象之前刺破它. 在vue中怎么写? 2:阻止默认行为 在vue中怎么写? 3:键盘事件 获取键码?通过事件对象来获取 注意:keydown事件和keyup事件的区别? keydown是在键