0
@interface ClassA : NSObject

@property (strong, nonatomic) dispatch_queue_t dispatchQ;
@property (strong, nonatomic) NSString *string;

@end

@implementation ClassA

- (id)init
{
    self = [super init];
    if (self) {
        _dispatchQ = dispatch_queue_create("com.classa.q", NULL);
    }

    return self;
}

- (void)longRunningTaskWithCompletion:(void(^)(void))completion
{
    dispatch_async(self.dispatchQ, ^{

        for (int i = 0; i < 10000; i++) {
            NSLog(@"%i", i);
        }

        dispatch_sync(dispatch_get_main_queue(), ^{
            self.string = @"Class A Rocks!";

            if(completion) {
                completion();
            }
        });
    });
}

@end

I'm thinking this code creates a retain cycle because the block in -longRunningTaskWithCompletion: captures self (to set the string property) in a block and adds the block to the dispatch queue property.

edelaney05
  • 6,822
  • 6
  • 41
  • 65
  • Possible duplicate of http://stackoverflow.com/questions/5023566/objective-c-calling-self-methodname-from-inside-a-block – Richard Brown Mar 20 '13 at 04:08

2 Answers2

12

There is a retain cycle, but it's temporary. The retain cycle looks like this:

  • self retains dispatchQ
  • dispatchQ retains the block
  • the block retains self

When the block returns, dispatchQ releases it. At that point, the retain cycle is broken. The block is deallocated and releases self.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • After getting some sleep, drinking a cup of coffee, and retracing my steps, this is exactly how I processed this. – edelaney05 Mar 20 '13 at 13:21
4

This is not a retain cycle. To have a retain cycle, self would need to retain the block while the block retains self. In the posted code, self does not retain the block. Therefore there is no retain cycle.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
rmaddy
  • 314,917
  • 42
  • 532
  • 579