Steven Fisher
Steven Fisher

Reputation: 44876

Declare that a variable must not be captured by a Block

Is there a way to prevent a variable from being captured into a block?

I'm wanting something like this:

[context performBlockAndWait:^{
    CoreDataObject *coreDataObject = [self getObject];
    NSString *name = coreDataObject.name;
    [self doThingWithCompletion:^{
        // I never want to use coreDataObject here, but I might want to use name.
    }];
}];

Yes, it's true that this won't capture coreDataObject. But if I accidentally use it in the block, it will. Is there a way to declare that coreDataObject should never be captured?

So far, the best I've come up with is this:

__block NSString *name;
[context performBlockAndWait:^{
    CoreDataObject *coreDataObject = [self getObject];
    name = coreDataObject.name;
}];
[self doThingWithCompletion:^{
    // coreDataObject is no longer in scope here
}];

However if doThingWithCompletion needs Core Data locking I've just turned one lock into two.

Upvotes: 1

Views: 44

Answers (1)

Ken Thomases
Ken Thomases

Reputation: 90601

You can just use a scope block (not the closure type of block, just the C compound-statement kind of block) to make sure that coreDataObject can't be used:

[context performBlockAndWait:^{
    NSString *name;

    {
        CoreDataObject *coreDataObject = [self getObject];
        name = coreDataObject.name;
    }

    [self doThingWithCompletion:^{
        // I never want to use coreDataObject here, but I might want to use name.
    }];
}];

In simple cases like this, you could also just eliminate the coreDataObject variable entirely:

    NSString *name = [self getObject].name;

Upvotes: 3

Related Questions