8

I have a simple method in my class:

- (void)getFormWithBlock:(DataCenterResultBlock)block {
    [SomeClass doSomeLongOperationWithParam:someParam 
                                  completionBlock:^(NSData *data, NSURLResponse *response) {
                                      //Success
                                      block(aVar, YES);
                                  } errorBlock:^(NSError *error) {
                                      //Failed
                                      block(nil, NO);
                                  }];
}

I read that you should copy blocks to the heap if you are doing something asynchronously because they are allocated on stack and once the call tree rewinds it will be gone.

But here, I am not copying it to heap but still I get no crash. Why? Thanks

0xSina
  • 20,973
  • 34
  • 136
  • 253

2 Answers2

11

Block variables are copied to the heap automatically by ARC compilers:

7.5. Blocks

...

__block variables of retainable object owner type are moved off the stack by initializing the heap copy with the result of moving from the stack copy.

EDIT I think I misunderstood the question: you asked about block objects themselves, not block variables. The answer in this case is slightly different, but it boils down to the same this: ARC does the correct thing automatically.

ARC knows that block literals must be copied if they're used after the current scope returns. Non-ARC code needs to explicitly copy and autorelease returned blocks:

return [[^{
    DoSomethingMagical();
} copy] autorelease];

With ARC, this simply becomes:

return ^{ DoSomethingMagical(); };

(from here)

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Just for the benefit of others reading this answer, the answer doesn't actually match the question here (probably just misread). The question is about passing a stack allocated block to another method. The answer refers to capturing __block variables within a block. Those are two different issues. – Firoze Lafeer Aug 21 '12 at 20:39
  • @FirozeLafeer You are absolutely right, I misread the question. I edited it to answer the actual question this time :) Thanks! – Sergey Kalinichenko Aug 21 '12 at 20:54
1

[SomeClass doSomeLongOperationWithParam:completionBlock:errorBlock:] should be copying the completion and error blocks.

If you look at the implementation of that method, it is probably doing the right thing and copying the block that you passed in. ARC or no ARC, that method should copy those blocks.

Firoze Lafeer
  • 17,133
  • 4
  • 54
  • 48