英语轻松读发新版了,欢迎下载、更新

Block的retain cycle问题太恶心了!

freecunix 发布于 2013年12月18日 | 更新于 2013年12月22日
无人欣赏。

比如:

ClassA* objA = [[[ClassA alloc] init] autorelease];
  objA.myBlock = ^{
    [self doSomething];
  };
  self.objA = objA;

就会导致self无法释放。。

只能 __weak MyClass* weakSelf = self;

然后objA.myBlock中: [weakSelf doSomething];

这种问题大家有什么经验避免吗??这个很难发现呀。

共21条回复
adad184 回复于 2013年12月18日

就是用weakSelf解决

hikui 回复于 2013年12月18日

没错,这个很难发现的。。。。只能遵守规则。而且有些地方该用回调的还是用回调的好。

另外,开了ARC之后,出现retain circle的地方会给出warning的。

freecunix 回复于 2013年12月18日

2楼 @hikui 这个开arc也没有警告呀,貌似。。

terryso 回复于 2013年12月18日

这个其实跟你用delegate时设置为retain一样。我觉得不是Block的设计恶心,是你不遵循规范而已。。。

nickel 回复于 2013年12月18日

4楼,我觉得嘛,这虽然确实是和delegate用retain的情况一样,但block的使用本来就是一种很“隐式”的模式,既然“隐式”,那么很多东西就应该更自动得处理,这样使用者关注得就更少些。所以我认为这也算是objc在内存自动回收机制上的不完美,还是太需要用户关心内存管理关系了,只是少了自己去引用加减法。如果能够把strong/weak这些东西完全去除才比较完美。

所以我觉得oc里的ARC对于我来说还只算是半成品或者过渡品,只是减少了开发者一些基本工作,但远远离不需要关心内存管理还很远。

董一凡 回复于 2013年12月18日

解决方案就是:传递NSObject的时候一定要在心里过一遍谁拥有谁,千万别以为开了ARC就不用内存管理了,引用计数和自动GC是有本质区别的。

另一个解决方案就是学C++,所谓不会C++的Obj-C程序员不是一个好C程序员

nickel 回复于 2013年12月18日

对,6楼 说得是本质问题。我觉得很多人一开始用OC就是用ARC的开发者,尤其是没有c/c++基础的,很容易把ARC理解为GC。

freecunix 回复于 2013年12月18日

5楼 @nickel 同意,arc很多地方还不完善,而且规则过于复杂,虽然自己malloc/free很麻烦,但至少规则很明确,很简单,写malloc就要写free。 arc是帮你完成了一些,还有一些需要自己注意,至于什么地方要注意,就是个问题了。。。

freecunix 回复于 2013年12月18日

6楼 @董一凡

7楼 @nickel

恩,做oc的大部分都是c/c++出身吧?可能正因如此,用arc才容易出问题。 大家都习惯手动了。忽然不用管了,就蒙了。。

terryso 回复于 2013年12月18日

5楼 @nickel 我觉得要真正做到不需要管理内存,真的只有GC才能做到。ARC只是比较先进的智能指针而已。。。手工管理内存的基本技能还是需要的,尤其是在跟CoreFoundation之类的底层C代码打交道时。我建议一开始还是从手工管理内存开始练手,等练得差不多了,才转到ARC。而且用ARC时,首先要先了解ARC相关的坑,这个推荐看iOS与OS X多线程与内存管理那本书,里面的ARC以及BLOCK等都讲得非常透彻。

adad184 回复于 2013年12月18日

我怎么觉得c/c++出身的 转OC|用ARC才不容易出问题呢

freecunix 回复于 2013年12月18日

10楼 @terryso 恩,谢谢。 我买本看看。

手动管理内存写了好几年了~ 今年才开始用arc,总是掉坑了。。。很多时候掉坑的原因都是没注意被引用了,比如在一个地方用了block,后来由于功能修改,另一个地方引用了block所属的对象。。

freecunix 回复于 2013年12月18日

11楼 @adad184 写c时候会很注意写free的。arc的话就容易忽略这件事。。 我

adad184 回复于 2013年12月18日

13楼 @freecunix ARC只是少让自己写点代码 我也是今年才转到ARC上的 之前也一直手动管理retain release

其实只要弄懂了strong weak, 基本就不会弄错了

幸好现在不用支持4.x了 那个unsafe retain也是一个坑

董一凡 回复于 2013年12月18日

9楼 @freecunix c和c++是两回事,如果你用过c++的shared_ptr, weak_ptr,这东西和ARC一模一样。然后C++的lambda表达式block基本是一回事。你会用这三个东西,那ARC想错都难

freecunix 回复于 2013年12月18日

14楼 @adad184 恩。。 arc还好,最近开始用block,block和arc放一起坑就更多了~~

freecunix 回复于 2013年12月18日

15楼 @董一凡 哦,c++很久很久以前用,好几年没用都忘没了。。依稀还能回想起来当前学c++时候有多痛苦,我还是不要在去捡c++了~~ 我喜欢轻量级的东西。 嘿嘿

riven 回复于 2013年12月19日

多用weakSelf不就可以么

morpheus1984 回复于 2013年12月21日

10楼 @terryso 是的。其实关于block内存管理 官方文档里有提到,可能大家都没注意到。

When a block is copied, it creates strong references to object variables used within the block. If you use a block within the implementation of a method:

If you access an instance variable by reference, a strong reference is made to self;

If you access an instance variable by value, a strong reference is made to the variable.

The following examples illustrate the two different situations:

dispatch_async(queue, ^{
  // instanceVariable is used by reference, a strong reference is made to self
  doSomethingWithObject(instanceVariable);});
id localVariable = instanceVariable;

dispatch_async(queue, ^{ /* localVariable is used by value, a strong reference is made to localVariable (and not to self).

morpheus1984 回复于 2013年12月21日

10楼 @terryso 是的。其实关于block内存管理 官方文档里有提到,可能大家都没注意到。

When a block is copied, it creates strong references to object variables used within the block. If you use a block within the implementation of a method:

If you access an instance variable by reference, a strong reference is made to self;

If you access an instance variable by value, a strong reference is made to the variable.

The following examples illustrate the two different situations:

dispatch_async(queue, ^{
  // instanceVariable is used by reference, a strong reference is made to self
  doSomethingWithObject});
dispatch_async(queue, ^{
  /*
    localVariable is used by value, a strong reference is made to localVariable
    (and not to self).
 */
  doSomethingWithObject(localVariable); });

本帖有21个回复,因为您没有注册或者登录本站,所以,只能看到本帖的10条回复。如果想看到全部回复,请注册或者登录本站。

登录 或者 注册
[顶 楼]
|
|
[底 楼]
|
|
[首 页]