5

Suppose I have a class (non-ARC environment):

@interface SomeObject : NSObject {
    UILabel *someLabel;
    dispatch_queue_t queue;
}
- (void)doAsyncStuff;
- (void)doAnimation;
@end

@implementation SomeObject

- (id)init {
    self = [super init];
    if (self) {
        someLabel = [[UILabel alloc] init];
        someLabel.text = @"Just inited";
        queue = dispatch_queue_create("com.me.myqueue", DISPATCH_QUEUE_SERIAL);
    }
    return self;
}

- (void)doAsyncStuff {
    dispatch_async(queue, ^{
        ...
        // Do some stuff on the current thread, might take a while
        ...
        dispatch_async(dispatch_get_main_queue(), ^{
            someLabel.text = [text stringByAppendingString:@" in block"];
            [self doAnimation];
        }
    }
}

- (void)doAnimation {
    ...
    // Does some animation in the UI
    ...
}

- (void)dealloc {
    if (queue) {
        dispatch_release(queue);
    }
    [someLabel release];
    [super dealloc];
}

If my block gets kicked off and then everything else holding a reference to the instance of this object releases it, am I guaranteed that dealloc won't be called because the nested block refers to an instance variable (and to self) -- that dealloc will happen after the nested block exits? My understanding is that my block has a strong reference to self, so this should be kosher.

2 Answers 2

3

This is fine, for the reasons you've stated.

The important thing to note is that you would create a retain cycle, if the class (represented by self) retained the block in any way. Because you're defining it in-line, and passing it to dispatch_async, you should be ok.

Sign up to request clarification or add additional context in comments.

2 Comments

This is why I prefer self->ivar.property, because I can see it retains self. Not just ivar.property, which in fact gets expanded by self->.
It is not a good idea to use self->ivar if self become nil it would cause a crash. It is better to define it as property when you use it in a block, and use __weak self to prevent retain cycle.
0

You are absolutely right. The block retains self in two cases:

  1. You use self inside the block.
  2. You access an instance variable directly inside the block.

Your nested block is good to go on both counts. Therefore, the dealloc will happen after the block has finished executing.

Another interesting thing to note is that your queue is also an instance variable. My initial thought was that because it is an instance variable, self also gets retained until the block has finished executing. However, what actually happens when I tested it out is only queue gets retained and self gets deallocated. I am not able to find documentation for this though.

1 Comment

"My initial thought was that because it is an instance variable, self also gets retained until the block..." No, queue is not used inside any of the blocks that I can see

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.