dev gr
dev gr

Reputation: 2431

where to release a __block variable?

I have following code snippet:

-(void) doSomething
{
    __block NSMutableArray *objArray = [[NSMutableArray alloc] initWithCapacity:0];
      [self performOperationWithBlock:^(void)
      {
         //adding objects to objArray
         .
         .
         //operation with objArray finished

         // 1. should objArray be released here?
      }];

      //2. should objArray be released here?
}

Should I autorelease the objArray?

Upvotes: 4

Views: 941

Answers (4)

Rui Peres
Rui Peres

Reputation: 25917

If it's an asynchronous call, it would make sense to create the NSMutableArray inside the actual block:

  [self performOperationWithBlock:^(void)
  {
     NSMutableArray *objArray = [[NSMutableArray alloc] initWithCapacity:0];

     //adding objects to objArray
     .
     .
     //operation with objArray finished

     // 1. should objArray be released here?
  }];

As you won't be needing it after the block (it only makes sense for the duration of the async operation), so in the end release it after you have used it. Or, you can simply:

     NSMutableArray *objArray = [NSMutableArray array];

And in this case you don't need to release it.

If it's a sync call, you should release it after the block.


Note: I am assuming you are populating the NSMutableArray before being used on the block, which means it makes sense to be created before the block starts.

Async approach:

-(void) doSomething
{
   // Remove the `__block` qualifier, you want the block to `retain` it so it
   // can live after the `doSomething` method is destroyed
    NSMutableArray *objArray = // created with something useful

    [self performOperationWithBlock:^(void)
     {
       // You do something with the objArray, like adding new stuff to it (you are modyfing it).
       // Since you have the __block qualifier (in non-ARC it has a different meaning, than in ARC)
       // Finally, you need to be a good citizen and release it.
     }];

    // By the the time reaches this point, the block might haven been, or not executed (it's an async call).
    // With this in mind, you cannot just release the array. So you release it inside the block
    // when the work is done
}

Sync Approach:

It assumes that you need the result immediately, and it makes sense when you do further work with the Array, after the block has been executed, so:

-(void) doSomething
{
   // Keep `__block` keyword, you don't want the block to `retain` as you
   // will release it after
    __block NSMutableArray *objArray = // created with something useful

    [self performOperationWithBlock:^(void)
     {
         // You do something with the objArray, like adding new stuff to it (you are modyfing it).
     }];
    // Since it's a sync call, when you reach this point, the block has been executed and you are sure
    // that at least you won't be doing anything else inside the block with Array, so it's safe to release it

    // Do something else with the array

    // Finally release it:

    [objArray release];
}

Upvotes: 5

Cy-4AH
Cy-4AH

Reputation: 4585

Option 2. Release it after [self performOperationWithBlock:...]. Block will retain and release yours objArray by himself. Releasing inside block is dangerous: block can be performed twice and then objArray will be released twice, but it's should de released once. So there is only one option left: 2.

Upvotes: 0

Taum
Taum

Reputation: 2551

If you're not using ARC, you should release the array when you no longer need it. According to the comments you added and assuming the doSomething method doesn't do anything with the array outside of the block, it should be at your 1. mark.

Upvotes: 0

trojanfoe
trojanfoe

Reputation: 122391

You should release it after the performOperationWithBlock: method has finished, in my opinion, provided that method is synchronous (i.e. works on the same thread as the calling thread).

If that method is asynchronous then it should be released within the block.

Upvotes: 1

Related Questions