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

I want to reuse an object reference for multiple calls of one block, and I wonder: what is the practical difference between the two following approaches?

Variable usage __block:

__block Widget *widget = [self buildNewWidget];

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

        gadget.widget = widget;
    }];
}

Variable usage static:

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 parts of the code are different from the semantic perspective, but (practically) I believe that they do the same basic job. I guess there is a difference with the perspective of memory management, the perspective of performance, or something else. Any ideas that illustrate these differences (or explain why they are not different) would be helpful.

+5
source share
4 answers

, -(void)useGadgetsOnWidgets { ... }.

ARC, , (.. useGadgetsOnWidgets ), , :

static widget . , -useGadgetsOnWidgets ( ), , . , / ( , __block:

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

, , :

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

, static ( ), - . ( , ).

:. , , ivar/property self:

-(Widget*)workingWidget {
  // Assuming _cachedWidget is an ivar
  if ([_cachedWidget isBroken]) {
    _cachedWidget = [self buildWidget];
  }
  return _cachedWidget;
}

-(void)useGadgetsOnWidgets {
  for(Gadget *gadget in self.gadgets) {
    [self useGadget:gadget withCallback:^{
      gadget.widget = [self workingWidget];
    }];
  }
}
+1

:

( , , , ...)

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>
+2

, -, .

- , . , - . , . if .

widget, , . , a __block . , .

+1

__ makes the variable available inside the block, for example, if it is global. If you use it inside a block, instead of copying it, it will be referenced and, since it will look like a global one, it will still be alive. But the next time you call this block of code, another variable will be pushed onto the stack.

static makes the variable visible only in scope, and it survives the full execution of the program. But if you call this block of code a different time, the variable will be the same.

-1
source

All Articles