简体   繁体   English

iOS-GCD对自我的弱引用

[英]iOS - GCD weak and strong reference to self

I was always using __weak references to self when I was in a block in GCD . GCD ,我一直在使用__weak引用self Everyone recommends that. 每个人都建议。 I know that strong reference to self (tested) in GCD can't produce retain cycles. 我知道在GCD中对self (经过测试)的强烈引用不会产生保留周期。 Apple recommends using a __weak reference to self and then a __strong reference to that _week reference to guarantee that self won't be nil when the block is executed. Apple建议使用__weak引用self,然后使用__strong引用_week引用,以确保执行该块时self不会nil

I have the following piece of code: 我有以下代码:

- (IBAction)startGCD:(id)sender {

    GCDVC* __weak weakSelf = self;

    [self.activityIndicator startAnimating];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1

        // VC2* __strong strongSelf = weakSelf;

        [weakSelf.proArray addObject:@"2"];

        [NSThread sleepForTimeInterval:10];

        NSLog(@"%@",weakSelf.proArray);

        dispatch_async(dispatch_get_main_queue(), ^{ // 2
            [weakSelf.activityIndicator stopAnimating];
        });
    });

}

Test 1 I press the button and the Indicator is spinning. 测试1我按下按钮,指示器旋转。 I press the back button before the GCD finish and the GCDViewController is being released. 我在GCD完成并且GCDViewController被释放之前按下了返回按钮。

Test 2 Then I uncomment the strong reference to self and I execute the same procedure. 测试2然后,我取消对自我的强烈引用,并执行相同的过程。 The GCDViewController is not released until the block has finished it work. 在块完成工作之前,不会释放GCDViewController。 But then its released. 但随后被释放。

Test 3 Now if I refer directly to self (without __weak or __strong ) I have the exact behaviour with Test 2. 测试3现在,如果我直接指代自我(没有__weak__strong ),我在测试2 __strong具有确切的行为。

So if I want to make sure that the self won't be nil when the block is executed what's the point of using a __strong reference to a __weak reference to self ? 因此,如果我想确保在执行块时self不会为nil,那么对__weak引用使用__strong引用对self何在? Do I miss something here? 我在这里想念什么吗? Is any example that would change the result of Test 2 & 3? 是否有任何示例会改变测试2和3的结果?

I was always using __weak references to self when I was in a block in GCD. 在GCD中的某个块中时,我一直在使用__weak引用self。 Everyone recommends that. 每个人都建议。

No. I don't know anyone that recommends that. 不,我不知道有人建议这样做。 Weak references make sense in some situations where there would be retain cycles. 在存在保留周期的某些情况下,弱引用是有意义的。 But whether a block should capture a weak or strong reference to any object (including the one self points to) depends on the particular memory management design of the code in question and 但是,一个块应该捕获对任何对象的弱引用还是强引用(包括一个self指向的对象),取决于所讨论代码的特定内存管理设计,并且

I know that strong reference to self (tested) in GCD can't produce retain cycles. 我知道在GCD中对自我(经过测试)的强烈引用不会产生保留周期。

Passing a block to dispatch_async on a global or main queue will NEVER produce a retain cycle. 在全局或主队列上将一个块传递给dispatch_async永远不会产生保留周期。

Now if I refer directly to self (without __weak or __strong) I have the exact behaviour with Test 2. 现在,如果我直接指代自我(没有__weak或__strong),我将具有测试2的确切行为。

Maybe you don't see any difference in this case. 在这种情况下,您可能看不到任何区别。 But they have different behavior in general. 但是它们通常具有不同的行为。 Basically, your question is what is the difference between the block capturing a strong or weak reference to the object pointed to by self . 基本上,您的问题是,捕获对self指向的对象的强引用或弱引用的块之间有什么区别?

The difference is in what happens, if the current object (object pointed to by self ) has been released by every other object that holds a strong reference to it, except potentially the block, and the block is executed afterwards asynchronously. 不同之处在于,如果当前对象(由self指向的对象)已经被持有该对象强引用的所有其他对象(可能是该块)释放了,并且该块随后异步执行。

  • If the block captured a strong reference to the current object, then that reference would keep the object alive during this whole time. 如果该块捕获了对当前对象的强引用,则该引用将使对象在整个时间内保持活动状态。 So the object is still alive and we can use it and send messages to it, etc. 因此,该对象仍然存在,我们可以使用它并向其发送消息,等等。
  • If the block captured a weak reference to the current object, then the current object has already been deallocated, when the last strong reference to it was released. 如果该块捕获了对当前对象的弱引用,则当释放对它的最后一个强引用时,当前对象已经被释放。 So the block's weak reference would be nil at this point, and the block is not going to do anything with it (it is either going to check strongSelf and return when it sees that it is nil , or it will send messages to strongSelf which is nil which does nothing). 因此,该块的弱引用此时将为nil ,并且该块将不对其执行任何操作(它要么检查strongSelf并在看到它为nil时返回,否则将向其发送消息到strongSelf nil ,什么都不做)。

So in one case stuff is done and in the other case nothing is done. 因此,一种情况下完成了工作,而另一种情况下则什么也没有做。

If the current object in your case is some UI element, like a view or view controller, then as long as it is in the view hierarchy, it is going to be retained by things in the view hierarchy, so you need to exit out of this view/view controller in order to have the situation where nothing else has a strong reference to it. 如果您当前的对象是某个UI元素(例如视图或视图控制器),则只要它在视图层次结构中,它就会被视图层次结构中的事物保留,因此您需要退出该视图/视图控制器,以便在没有其他东西对其有强烈引用的情况下。

In your case, all you do inside the block is [weakSelf.activityIndicator stopAnimating]; 就您而言,您在块内要做的只是[weakSelf.activityIndicator stopAnimating]; , ie a change to the UI. ,即更改UI。 It doesn't matter whether this command is run or not, because, remember, the view containing this has already stopped displaying. 该命令是否运行无关紧要,因为请记住,包含该命令的视图已经停止显示。 Nobody can see this activity indicator. 没有人可以看到此活动指示器。 So what difference does it make if you stop it or not? 那么,如果不停止,有什么不同呢? But this is specific to this case. 但这是特定于此情况的。 In general, you can imagine that the command inside the block changes some global state, or sends something over the network or something, where there is a big difference between if you do it or not. 通常,您可以想象该块中的命令会更改某些全局状态,或者通过网络或某些内容发送某些内容,如果您不这样做,则两者之间会有很大差异。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM