Search code examples
objective-cobjective-c-blocks

Copying a changing object to inside a block, so the block has the correct value


I have this loop that has this NSDictionary. Every turn, this NSDictionary is created with new values. The problem is that this loop fires an async block to be executed. Something like:

for (int i=0; i<10; i++) {
  NSDictionary *aDict = [self fillDictWithCurrentValues];
    dispatch_async(dispatch_get_main_queue(), ^{
       executeBlock(aDict);
  });
}

My problem is this. I want this block to execute with the dictionary passed to it but because the loop will execute faster, it will go out of scope when executeBlock runs. So, two questions:

  1. I suspect every block will hold a reference to its correspondent aDict, so they will not crash even if they execute when the caller is out of scope, right?
  2. aDict is a strong reference. Do I need to create a __weak version before calling the dispatch_async and a __strong reference inside the dispatch_async so there is no retain cycle?

Solution

  • You ask:

    1. I suspect every block will hold a reference to its corresponding aDict, so they will not crash even if they execute when the caller is out of scope, right?

    It will keep strong reference while the block runs, so you don't have to worry about it being deallocated on you.

    That having been said, there is a question of what fillDictWithCurrentValues does. If it's creating a new dictionary each time, you're fine. But if it's returning some reference to some dictionary that is shared, this can be problematic. It just depends upon what this method is doing.

    1. aDict is a strong reference. Do I need to create a __weak version before calling the dispatch_async and a __strong reference inside the dispatch_async so there is no retain cycle?

    There's no strong reference cycle because when dispatch_async is done running the block, the block will be released.

    You might still use the weakSelf pattern if (a) there's a possibility that self might be deallocated before the closures are done running; and (b) you think it's important that the closures don't prevent that from happening. But usually, when dispatching updates back to the main queue (which you only do with very fast routines), you don't worry about it.