Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Within a block, what is the practical difference between a __block variable and a static variable?

I want to reuse an object reference across multiple calls of a single block, and I'm curious: What is the practical difference between the following two approaches?

Using a __block variable:

__block Widget *widget = [self buildNewWidget];

for(Gadget *gadget in self.gadgets) {
    [self useGadget:gadget withCallback:^{
        if([widget isBroken]) {
            widget = [self buildNewWidget];
        }

        gadget.widget = widget;
    }];
}

Using a static variable:

for(Gadget *gadget in self.gadgets) {
    [self useGadget:gadget withCallback:^{
        static Widget *widget;

        if(!widget || [widget isBroken]) {
            widget = [self buildNewWidget];
        }

        gadget.widget = widget;
    }];
}

Obviously these two chunks of code differ from a semantic perspective, but (practically speaking) I believe they do the same basic work. My guess is that there is a difference from a memory management perspective, a performance perspective, or something else. Any insights that illustrate these differences (or explain why they are not different) would be helpful.

like image 619
wxactly Avatar asked Oct 22 '22 18:10

wxactly


1 Answers

An example is worth a thousand words:

(And yes, this is a very simplistic example, but it is mostly equivalent to what you were doing...)

for (int i = 0; i < 3; i++)
{
    // Your example encompasses this scope,
    // not taking into account that we may execute this code multiple times:

    // Call the block
    (^{
        // Every instance/execution of this block will have the same object.
        static Obj *o;

        // Initialize static object
        static dispatch_once_t once;
        dispatch_once(&once, ^{
            o = [Obj new];
        });

        NSLog(@"Object is: %@", o);
    })();
}
// Output:
//   Object is: <Obj: 0x100109fd0>
//   Object is: <Obj: 0x100109fd0>
//   Object is: <Obj: 0x100109fd0>

for (int i = 0; i < 3; i++)
{
    __block Obj *o = [Obj new];

    // Call the block
    (^{
        // This block uses the object from its enclosing scope, which may be different.
        NSLog(@"Object is: %@", o);
    })();
}
// Output:
//   Object is: <Obj: 0x105100420>
//   Object is: <Obj: 0x1003004f0>
//   Object is: <Obj: 0x105300000>
like image 80
jtbandes Avatar answered Oct 28 '22 22:10

jtbandes