-1

Consider a UIViewController subclass that does this (using ARC):

- (void)viewDidLoad {
    __weak id wself = self;
    dispatch_async(backgroundQueue, ^{
        longRunningOperation();
        dispatch_async(mainQueue, ^{
            [wself updateView];
        });
    });
}

Questions

  1. What happens if the view controller deallocs while the block is still executing?
  2. How can I have the block immediately stop executing if the view controller deallocs while it is running?
Steveo
  • 2,238
  • 1
  • 21
  • 34

4 Answers4

1

If you need to support cancelling then NSOperation/NSOperationQueue are much easier to work with.

If the object is deallocated then in most cases it should cause no issue as calling a method on nil is a noop. However if you use any direct ivar access (self->myIvar) then you could run into crashes as you'll be dereferencing nil. One way around this is to get a strong reference before you do anything with the object:

- (void)viewDidLoad
{
  [super viewDidLoad];

  __weak __typeof(self) weakSelf = self;
  dispatch_async(backgroundQueue, ^{
    longRunningOperation();

    dispatch_async(mainQueue, ^{
      __typeof(weakSelf) strongSelf = weakSelf;
      strongSelf->myIvar;
    });

  });
}
Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
Paul.s
  • 38,494
  • 5
  • 70
  • 88
0

Using wself in this code may allow the view controller to be deallocated while longRunningOperation is still executing. I don't think that passing a weak self is necessary in this case because there is not an opportunity for a circular reference involving the blocks.

As far as interrupting the execution, the best thing to do would be to set a flag in ViewDidDisappear that the view is no longer visible and check that flag before executing updateView.

Jack Cox
  • 3,290
  • 24
  • 25
  • Then the operation would cancel if the user switched to another app or the app presents another view controller modally. – Aaron Brager Feb 16 '14 at 00:09
0

Check this SO question, there's a good answer there with details describing GCD's lack of cancellation features.

Other than that, if you try executing this code and checking the value of wself and self (separately, comment out self when checking wself) by the time the block executes, you'll see that wself becomes nil whereas self still has a value.. so I think you're right in avoiding directly referencing self here. If you check both wself and self in the same block, you'll wself still has a value also. So this block is able to basically keep self alive a little longer if you directly reference it within the block. So using wself will ensure that you don't inadvertently keep the thing alive longer than it's intended to, and thus the selector doesn't actually end up doing anything.

So you could either check whether wself has become nil in the block when it executes, or you could just rely on Objective-C's ability to quietly do nothing when passing a message to nil (as long as it's not an unrecognized selector).

Community
  • 1
  • 1
drhr
  • 2,261
  • 2
  • 17
  • 35
0

If you need to cancel some operations better program there with NSOperation with NSOperationQueue. This will allow you to cancel operations which should be deallocated together with your view

Grzegorz Krukowski
  • 18,081
  • 5
  • 50
  • 71