0

The code below is from the Big Nerd Ranch iOS programming book, 3rd edition. It's a class method that checks whether the singleton class BNRItemStore has been instantiated. If it has, it returns the singleton instance, and if it hasn't it creates it. The part I don't understand is the static variable. I know that static variables keep state, however, wouldn't calling the method a second time reset the *sharedStore back to nil? i.e. isn't this an assignment which would erase the creation of the singleton instance once the method was called again?

static BNRItemStore *sharedStore = nil;

Method

+(BNRItemStore *)sharedStore
{
   static BNRItemStore *sharedStore = nil;
   if (!sharedStore)
       sharedStore = [[ super allocWithZone:nil ] init ];
   return sharedStore;
}
BrainLikeADullPencil
  • 11,313
  • 24
  • 78
  • 134
  • It's a weirdness of C's `static` implementation: Regardless of where the static variable is declared, any initialization that occurs **in the declaration statement** is only executed once. – Hot Licks Feb 22 '14 at 19:48

3 Answers3

2

Unfortunately, C terminology is really confusing. static has nothing to do with singletons, standing still, not changing, or anything like that. It has to do with the level at which storage takes place.

A variable declared inside a method/function is normally an automatic variable, meaning that it goes out of existence when the scope ends (i.e. execution reaches the end of the surrounding curly braces). A variable declared static, however, is stored at the level of the file that holds the code; once the file is loaded, this variable persists, even though it is declared inside a method/function.

Now we come to the question of how you will know whether this variable has ever been assigned a value, because you only want to assign it once. In theory, a static variable has a zero value when it is initially declared. Thus, if you said merely

   static BNRItemStore *sharedStore;

...the code might work, because zero is nil for an instance, so we could test against nil and assign a value only in that case. However, it does no harm to make assurance double sure. Thus, we typically initialize the variable to nil when we declare it, just so we can be sure our nil test will work the first time.

That initializer, as you've already been told, will then take effect only once, because after that, the value persists and so the variable never needs to be initialized again (and never is).

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • One explanation is that the word "static" describes where in memory the variable is stored. A normal automatic variable gets stored in a different place in memory depending on where it is in the call stack automatically, but a static variable is always stored in the same place, so when it is accessed again in a different context it still contains the same value. – Douglas Feb 23 '14 at 18:41
1

The code is fine, the initialiser only gets called the first time.

Douglas
  • 36,802
  • 9
  • 76
  • 89
  • I think you misunderstood my question. I'm asking why the initializer wouldn't get called a second time. In other words, if I called sharedStore a second time, doesn't the static variable *sharedStore get set to nil, which would then mean there is no shared store so the code inside `if(!sharedStore)` gets run? – BrainLikeADullPencil Feb 22 '14 at 15:52
  • Is this more helpful? http://stackoverflow.com/questions/5567529/what-makes-a-static-variable-initialize-only-once This behaviour is the same in Objective C. – Douglas Feb 22 '14 at 15:54
  • yes now i get it thanks – BrainLikeADullPencil Feb 22 '14 at 15:56
  • _“the initializer only gets called the first time”_ Or more accurately, the initializer is “baked-in” at compile-time— so the initial value is part of the program's executable (like how `const` values work) and when the program is launched and the executable's memory layout is loaded onto the stack, the initial value is loaded alongside everything else that's static (`static` vars, `const`s, `class`es). – Slipp D. Thompson Nov 06 '16 at 01:29
0

Static initializers are guaranteed by the language specification to only be executed one time, (and that's actually done at application start time, not as a part of function execution) so the static variable will only be nil the first time the function is executed.

David Berry
  • 40,941
  • 12
  • 84
  • 95