Clarification on an Objective-C Singleton Example - objective-c

I'm just getting started on Objective-C and I came across this example on creating a singleton:
+ (BNRItemStore *) sharedStore
{
static BNRItemStore *sharedStore = nil;
if (!sharedStore)
sharedStore = [[super allocWithZone:nil] init];
return sharedStore;
}
I understand what's he's trying to do - which is to return the same instance if it's existing and create a new one if it's not. What bothers me is this line:
static BNRItemStore *sharedStore = nil;
Won't this line reset the sharedStore to a nil value everytime the method is called? I don't see how the method will be able to return the previously existing instance if this line always sets it to nil.
Thanks in advance.

This is an element which Objective-C inherits from standard C. Any variable with static storage duration (which the static type specifier explicitly declares) is only initialized once, and the c standard says that this happens before the program starts.
6.2.4 3) An object whose identifier is declared with external or internal linkage, or with the storage-class specifier static has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
Note that it also mentions that if the variable with static storage duration is of 'pointer type', then it is automatically set to a NULL pointer (which is what nil is), so if you want, you can omit the = nil part of the declaration if you think it improves the readability of your function.

Won't this line reset the sharedStore to a nil value everytime the method is called?
Because sharedStore is static, it will be initialized (the = nil bit) the first time it is called. Subsequent calls will skip these instructions.
I don't see how the method will be able to return the previously existing instance if this line always sets it to nil.
Because it is static the variable and its value will remain in memory after the method exits.
Basically, you can think of this as a global variable, but it is accessible only to +sharedStore.

Related

Keeping objectiveC object valid outside the scope of a function

I'm a bit confused about ARC behaviour when setting variable that is an input pointer, and is expected to remain valid outside function scope.
considering the following example that uses openDirectory framework.
#interface bbb
-(bool)doSomethingWithADRecord:
-(void)obtainADRecord(NSString*)user
-(NSString*)getADrecord:(ODAttributeType)attr fromRecord:(ODRecord*)record;
#end
#interface bbb {
ODRecord *_myRecord;
}
#end
#implementation bbb
-(void)doSomethingWithADRecord:
{
// here we access _myRecord and expect it to be valid.
}
-(bool)obtainADRecord:(NSString*)user
{
...
// here I call the method that will set the member _myRecord from type ODRecord*
// whose scope related to the lifespan of the containing class (bbb)
[self getADrecord:attr toRecord:_myRecord];
}
// the following function should set the variable record to be used by the caller.
-(NSString*)getADrecord:(ODAttributeType)attr fromRecord:(ODRecord*)record {
...
// here a set an ODQuery object.
ODQuery *query = [[ODQuery alloc] initWithNode ...
// queryResults is an array of items from type ODQuery*
NSArray* queryResults = [query resultsAllowingPartial:NO error:&err];
for(ODRecord *item in queryResults) {
if (/*some logic*/)
{
//option 1: just regular set operator, expecting the ARC will do the retain itself
record = item;
//option 2: explicits take a reference on that item.
record = [[item retain] autorelease];
return #"found item";
}
}
}
#end
To Clarify my question, I seek to know which one of the 2 options I stated above is the correct one , in terms of passing the reference to record and eventually to _myRecord, so it will store the correct value even after the temporal list of queryResults will be cleaned.
Notice that in both options I simply setting the pointer value without initiate new object from type ODquery and copying the data to this new object.
thanks !
I'd like to know whether simply doing record = item will be enough for the data pointed by this object to last beyond the scope of the function getADrecord
You are misunderstanding how parameters work; a parameter, such as record, is essentially a local variable which is initialised to the value passed in the call.
Therefore any assignment of an object reference to record will have zero effect on the lifetime of the referenced object outside of the scope of getADrecord as record is local to the function.
To return a value of type T via a parameter the type of the parameter must be of type "pointer to a variable of type T". An example with a simple value type:
- (void) add:(int)value // an int value
to:(int *)ptrToVariable // a pointer to an int variable
{
// note the need to indirect (`*`) through pointer stored in
// `ptrToVariable` to access the pointed at variable
*ptrToVariable = *ptrToVariable + value;
}
int x = 31;
[self add:11 to:&x]; // &x creates a pointer to the variable x
// x = 42 after call
Now you don't want to return a simple value type but a value which is a reference to an object and you wish ARC to manage the lifetime correctly. This is a little more complicated.
Under ARC a variable which holds a reference to an object has both a type and an ownership attribute; this attribute informs ARC how to handle storing references in the variable. The common ownership attributes are __strong and __weak, without an explicit attribute __strong is assumed. So your instance variable declaration is shorthand for:
ODRecord __strong *_myRecord;
This declaration means that for any reference to an ODRecord stored into _myRecord ARC will keep the referenced ODRecord alive at least as long as _myRecord exists and the reference is not overwritten by a different reference or nil. It is "at least as long" as the same reference could be stored elsewhere and these will also effect the lifetime.
Almost there! To return a reference to an ODRecord via a parameter the type of the parameter must be "pointer to a variable of type strong reference to ODRecord, i.e.:
- (NSString *)getADrecord:(ODAttributeType)attr
fromRecord:(ODRecord * __strong *)record
now an assignment such as:
*record = item;
will result in an assignment to the pointed-at variable and as that variable is of type ODRecord __strong * ARC will ensure the referenced ODRecord will live at least as long as a reference to it is stored in the pointed-at variable.
Your call to this method must pass a pointer to your variable:
[self getADrecord:attr toRecord:&_myRecord];
Notes:
"out" parameters are not often used in Objective-C with the notable exception of error returns – these are of type NSError * _autoreleasing * and Apple names this usage as "call-by-writeback".
For a deeper explanation of ARC and returning values via parameters see Handling Pointer-to-Pointer Ownership issues in ARC and NSError and __autoreleasing
Important:
As pointed out by #matt in the comments your code contains retain and autorelease calls which are forbidden in ARC and therefore if your code is compiling you DO NOT have ARC enabled. For new projects ARC will be enabled, for existing projects you may need to enable it your project's Build Settings, the setting is called "Objective-C Automatic Reference Counting".
A call to "autorelease" means the object has an additional retain count that will go away when you leave the current autorelease scope, which is typically when the current event is finished.
record = item is obviously not enough, because record's retain count goes away when records leaves scope, that is when the function returns.
But what you do - calling autorelease for each item makes sure that all the items remain allocated for a while, not just "record".

Objective C - What makes a static variable initialize only once?

I came from another programming language. I can understand singleton pattern. But I got confusion in ObjectiveC's Singleton Implementation.
Actually, I understand the lifetime of a static variable. But What makes a static variable initialize only once?
#implementation MyManager
+(instancetype)sharedInstance {
// structure used to test whether the block has completed or not
//Doubt 1 - If this method called second time, how it is not reset again to 0. How it is not executed second time?
static dispatch_once_t p = 0;
// initialize sharedObject as nil (first call only)
//Doubt 2 - If this method called second time, how it is not reset again to nil, How it is not executed second time?
__strong static MyManager * _sharedObject = nil;
// executes a block object once and only once for the lifetime of an application
dispatch_once(&p, ^{
_sharedObject = [[self alloc] init];
});
// returns the same object each time
return _sharedObject;
}
#end
In computer programming, a static variable is a variable that has been allocated statically so that its lifetime or "extent" extends across the entire run of the program.
https://en.wikipedia.org/wiki/Static_variable
The call to dispatch_once makes it initialize only once.
dispatch_once takes a pointer to a static memory location. It does effectively the following:
lock location; if anyone else has locked location, block until we can
if (location is unset) {
do_thing
set location
}
unlock location
But it does this in a much faster way that doesn't require a real lock (it does require a special CPU instruction, though, called "compare and swap.") If you want more details, see Mike Ash's excellent explanation. But for most uses, you can just accept that dispatch_once, if used correctly, will only run once per execution of the program.

Check if a pointer is nil before instantiating

I'm new to Objective-C and I got really confused when I saw the if check in the getter of a property:
- (XXX)name {
if (!_name) _name = [[XXX alloc] init];
return _name;
}
Why do you have to check if the pointer is nil when instantiating? Isn't that all objects starts with 0(nil)? Why can't you just have the pointer point to the newly instantiated object on the left?
You can see the point of this when you consider that name is called several times. The first call on a particular instance will allocate _name. In the subsequent calls _name wouldn't be nil, so the previously allocated item would be returned.
This is a lazy initialization pattern. This implementation is fine in single-threaded environments, and in environments where objects with this method are not shared among threads.
In concurrent environments you should use a thread-safe version of this pattern, which uses a lock, or the dispatch_once method.
Why do you have to check if the pointer is nil when instantiating?
The second time you call the getter method, it's already instantiated. This pattern is used when you only want to instantiate the property once. If it's nil you haven't done it yet. If it's non nil just return the value.
Isn't that all objects starts with 0(nil)?
Yep. If it's nil that means you need to instantiate it. So go ahead and do that, and from then on return that instance.
Why can't you just have the pointer point to the newly instantiated object on the left?
Huh? I have no idea what you are asking here.
This is a very common mini-pattern in Objective-C. You see it, for example, in custom property getters. The idea is to create an object, but only if you haven't created one before (and if you have, just return it). As #Nicholas Hart says in his comment, this also helps achieves lazy initialization (an object is created if and when it is referenced.
E.g.:
- (MyType *)myProperty
{
if(!_myProperty)
{
_myProperty = [[MyType alloc] init];
}
return _myProperty;
}
// somewhere else, you want to use the property:
[self.myProperty doSomething];
In the call to doSomething, the getter method myProperty will be called, and the _myProperty ivar (which is behind the myProperty property) will be initialized, if necessary.

Singleton objective c clarification

as I continue my studies the book implemented a singleton.
I understood the reason why use it but I just wanted some clarification regarding the code.
+ (BNRItemStore *)defaultStore
{
static BNRItemStore *defaultStore = nil;
if(!defaultStore)
defaultStore = [[super allocWithZone:nil] init];
return defaultStore;
}
In the line static BNRItemStore * defaultStore = nil; until the return statement.
My question is; all the time that I call this class, [[BNRItemStore defaultStore] someMethod]; in another class or part of the app, the defaultStore variable will be set to nil?
Cheers
It's important to understand that the static keyword has two effects. One is that it makes that variable exist before the method is called, and persist after it returns, so that it will be available for the next call. The other effect is more subtle -- the "assignment" that initializes the static variable is executed when the code is loaded, not when the method is called. So it does not get reinitialized on every call.
But since the variable exists "outside" of the method, it's name should be unique -- don't use the same name in another singleton in this class or another one.
That's the initializer of a variable with static storage duration. The value will be set when the executable is loaded into memory.
Note that its not necessary to explicitly set the value to nil as all variables with static storage duration are automatically set to 0.
For function-static variables the line
static BNRItemStore *defaultStore = nil;
is not an assignment. Rather, it is static initialization, which happens only once - the first time the code goes through your function. In subsequent invocations the value will not be nil, because you assign a non-nil value to it.
Your implementation is safe in single-threaded environments. For concurrent environments you would need to add some form of synchronization.
Static variables are initialized just the one time when the function/method is first called. After that, you can basically pretend the line doesn't exist.
Apple recommends something like the following
+ (BNRItemStore *)defaultStore
{
static BNRItemStore *defaultStore = nil;
static dispatch_once_t done;
dispatch_once(&done,
^{ defaultStore = [BNRItemStore alloc]init];});
return defaultStore;
}
The above code assumes ARC - If not using ARC you would have to define do nothing retain, release, autorelease, and dealloc methods.

Is there anything that can go wrong when I use static to implement a singleton?

I'm implementing a singleton class (and lets not get into the discussion if that is wrong or not). I have a method to get the instance of this class, which is lazily initialized:
+ (FFDataManager *)sharedDataManager {
static FFDataManager *dm = nil;
if (!dm) {
dm = [[FFDataManager alloc] init];
}
return dm;
}
Is there anything I should look out for when doing this using static (inside of the method) as opposed to creating a global variable? Is there anything that can go wrong, all tutorials on the Internet use a global variable.
My preferred singleton implementation looks like:
+ (MyClass *) sharedInstance {
static dispatch_once_t predicate = 0;
__strong static MyClass *shared = nil;
dispatch_once(&predicate, ^{
shared = [[self alloc] init];
});
return shared;
}
Using dispatch_once makes sure this is also thread safe. Your code would allocate twice when accessed by multiple threads at the same time.
To answer the original question (others have address the best way to do initialization):
Is there anything I should look out for when doing this using static (inside of the method) as opposed to creating a global variable?
No.
The difference is over visibility and not lifetime.
A global's (with or without static) lifetime is that of the application execution.
A global without static is visible throughout the whole application. From anywhere else it can be referenced by naming it in an extern statement.
A global with static is visible just in the containing compilation unit (which is typically a single file, but #import/#include can change that).
A variable declared within a function/method as static is a global which is only visible within that function/method.
If you're using a global in just one function what you've done is good - it limits the visibility to just where it is needed while keeping execution-lifetime. Any initializer is run once, just as for file-level globals.
What you create is a static local variable. Static local variables retain their value through successive method invocations. They can only be accessed from within the method which they are defined in. When apps start static local variables are set to 0 once.
So what you do in my opinion is with every call of sharedDataManager you declare a new static local variable and set it to nil. I don't think that's necessary or even good. And also every time if (!dm) checks dm it is nil because you set dm to nil the line before.
I'd go with the static global approach.
Edit:
Have a look at http://www.johnwordsworth.com/2010/04/iphone-code-snippet-the-singleton-pattern/