如果一个强属性具有一个涉及自我的障碍,那是一个保留周期吗? [英] If a strong property has a block that refers to self, is that a retain cycle?

查看:76
本文介绍了如果一个强属性具有一个涉及自我的障碍,那是一个保留周期吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如:

[self.contentWrapperView addGestureRecognizer:
   [UITapGestureRecognizer recognizerWithHandler:^(UIGestureRecognizer *sender, 
                                                   UIGestureRecognizerState state, 
                                                   CGPoint location) {
        if (self.customEditing) {
        [self setEditingMode:NO Animated:YES];
      }
    }]];

contentWrapperViewself的强属性,并且假定contentWrapperView对识别器块具有强引用.在块中使用self是否会导致保留周期?这是我唯一不了解的部分.

Where contentWrapperView is a strong property on self, and presuming contentWrapperView has a strong reference to the recognizer block. Is using self in the block going to lead to a retain cycle? This is the only part I don't quite understand.

推荐答案

从保留周期的实际意义上考虑保留周期:由您拥有的对象保留自己.

Think about a retain cycle in terms of what it actually is: a retention of yourself by an object that you own.

按照Cocoa和Cocoa-Touch的说法,这意味着您拥有 strong 的任何变量都不能反过来强烈拥有 you .通常可以通过声明需要拥有其父级weakunsafe_unretainedassign的属性来解决此问题.这会因块而变得复杂,而块通常像闭包一样捕获对它们中每个变量的const或保留引用(显然,__block限定符甚至使情况更复杂).

In Cocoa and Cocoa-Touch's terms, that means that any variable that you own strongly cannot, in turn, own you strongly. This is often gotten around by declaring a property that needs to own its parent weak, unsafe_unretained or assign. This gets complicated by blocks, which, acting as closures typically do, capture const or retained references to every variable within them (obviously, complicated even further by the __block qualifier).

我不会尝试从块的角度来看这个问题,而是尝试将其抽象为带有两个类的示例,这对于OO lang语言的人来说通常更容易实现:

Instead of looking at this from the standpoint of the block, I'll try to abstract it into an example with two classes, which is often more approachable for those in an OO lang:

假设我有一个类MyImportantObject,它需要对另一个类MyWorkerClass做一些工作.我们通常希望对MyWorkerClass进行强有力的引用,因为也许我们希望它坚持下去,以便以后可以做更多的工作,或者一遍又一遍地继续调用相同的worker方法:

Let's say I have class MyImportantObject, which needs to do some work with another class MyWorkerClass. We'd usually want a strong references to MyWorkerClass, because maybe we want it to stick around so we can do a little more work later on, or continue to call the same worker method over and over:

@interface MyImportantObject : NSObject 

@property (nonatomic, strong) MyWorkerClass *workerObj;

@end

反过来,我们的工作人员需要稳定引用其需要工作的所有MyImportantObject属性(否则它不能工作).因此,引用self的块将执行哪些操作,而不是对每个变量采用const或保留引用,而是对其父项保留保留引用!

In turn, our worker needs a stable reference to all of MyImportantObject's properties it needs to work (else it can't work!). So what blocks that reference self do, instead of taking a const or retained references to every variable, they take a retained reference to their parent!

@interface MyWorkerClass : NSObject 

@property (nonatomic, strong) MyImportantObject *workerObj;

@end

这意味着,如果您尝试使用MyImportantObject的辅助对象,它们将相互保留,并且不会被正确地释放!巨大的不行.

What this means is that if you attempted to use MyImportantObject's worker object, they'd retain each other, and neither would be deallocated properly! Huge no-no.

通过将self分流到__weak(或MRC下的__block)指针,我们得到的引用看起来像这样:

By shunting self into a __weak (or __block under MRC) pointer, we instead get a reference that looks like this:

@interface MyWorkerClass : NSObject 

@property (nonatomic, weak) MyImportantObject *workerObj;

@end

没有更多的保留周期,每个人都很高兴,当父母沿着恐龙的方向走时,每个人都被适当地释放了.

No more retain cycles, everybody's happy, everybody gets deallocated properly when the parent goes the way of the dinosaur.

但是还有一个难题:我们如何处理weak参考?毕竟,假设好的ol'编译器出现了,并以快速的-release从您的下方拉出self.由于归零弱指针,您现在在块中有一个运行amok的nil指针.这可能导致它实际上什么也没做,而您坐在那里挠头想知道为什么.这导致了我称之为弱劲舞的发明.

But there is one more piece of the puzzle: What do we do about the weak reference? After all, let's say the good ol' compiler comes around and yanks self out from under you with a quick -release. Because of that zeroing weak pointer, you now have a nil pointer running amok in your block. This can lead to it literally doing nothing, while you sit there and scratch your head wondering why. This has led to the invention of, what I will term, the weak-strong dance.

J_mcnally的示例缺少舞蹈中的关键一步,即自我指针的重新增强".但是,在我们为避免保留周期而费尽心思之后,为什么还要这样做呢?这是因为我们的X的强副本没有被块保留,而是被块的 scope 保留.用英语来说,这意味着我们强大的self仅在到达块的末尾时才释放,从而不仅保证了安全的内存循环,而且也不会从我们下面释放它.正确的修复程序如下所示:

J_mcnally's example is missing one crucial step in the dance, the "re-strongification" of your self pointer. But, why would we want to do that after we just went to all the trouble to avoid a retain cycle? It's because our strong copy of X isn't retained by the block, it's retained by the block's scope. In english, it means that our strong self will only deallocate once the end of the block has reached, thus guaranteeing not only a safe memory-cycle, but that it will not get deallocated out from under us. A proper fix looks like this:

__weak id weakSelf = self;
[self.contentWrapperView addGestureRecognizer:[UITapGestureRecognizer recognizerWithHandler:^(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location) {
    id strongSelf = weakSelf;
    if ([strongSelf customEditing]) {
        [strongSelf setEditingMode:NO Animated:YES];
    }
    //Do some other stuff before strongSelf passes out of scope.
}]];

这篇关于如果一个强属性具有一个涉及自我的障碍,那是一个保留周期吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆