SpaceDog SpaceDog - 1 month ago 9
Objective-C Question

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?


Rob Rob
Answer

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.