Singleton not initializing correctly - objective-c

I have the following code that I am calling using this statement: SQLiteDB *db = [[[SQLiteDB alloc] init] autorelease];
The problem is "sharedSQLiteDB" is not being called, but rather "allocWithZone" is, and therefore "checkIfDatabaseExists" is not being called, which is where the database is created.
I don't understand why... (i.e. what am I doing wrong?)
#import "SQLiteDB.h"
static SQLiteDB *sharedSQLiteDB = nil; // makes this a singleton class
#implementation SQLiteDB
#synthesize searchPaths, documentPath, databasePath, cDatabasePath;
#pragma mark Singleton Methods
+ (SQLiteDB *) sharedSQLiteDB {
if(!sharedSQLiteDB) {
sharedSQLiteDB = [[SQLiteDB alloc] init];
[sharedSQLiteDB checkIfDatabaseExists]; // check to see if d/b exists
}
return sharedSQLiteDB;
}
+(id)allocWithZone:(NSZone *)zone { // makes sure another instance is not allocated
if(!sharedSQLiteDB) {
sharedSQLiteDB = [super allocWithZone:zone];
return sharedSQLiteDB;
}
else {
return nil;
}
}
-(id)copyWithZone:(NSZone *)zone {
return self;
}
-(void) release {
// no-op
}

In the singleton pattern your use pattern should be:
SQLiteDB* db = [SQLiteDB sharedSQLiteDB];
They way you are calling it doesn't fit the singelton pattern. All access should be through your sharedSQLiteDB message.
In other words you shouldn't be initializing via typical Cocoa patterns (SQLiteDB *db = [[[SQLiteDB alloc] init] autorelease]; is incorrect and full of problems) outside the scope of the class.
In a singleton using the default initialization pattern for the language (alloc/init for ObjC or the default constructor for C++) should generate a compile time error message since the constructor/init method should be protected.
See the Wikipedia entry. consult the Design Pattern C++ bible. There is even a version for Cocoa
Good luck.

It isn't executing your + (SQLiteDB *) sharedSQLiteDB method because you're not actually calling that method anywhere.
As you've seen, when you call [[SQLiteDB alloc] init], the allocWithZone method is called.
Change your call to be SQLiteDB *db = [SQLiteDB sharedSQLiteDB], which will call your checkIfDatabaseExists method in this case. However, if [[SQLiteDB alloc] init] is called somewhere else, then the checkIfDatabaseExists method call will still be skipped.
Maybe consider moving the checkIfDatabaseExists method into an init method so that it will be called for both your singleton method and your allocWithZone.

Honestly I don't see any error...
However I post the code I used to create a Singleton. It's from a source that now I don't remember the link... it's not my code.
static DataManager *_instance;
#implementation DataManager
+ (DataManager*)sharedInstance
{
#synchronized(self) {
if (_instance == nil) {
_instance = [[super allocWithZone:NULL] init];
// Allocate/initialize any member variables of the singleton class her
// example
//_instance.member = #"";
}
}
return _instance;
}
#pragma mark Singleton Methods
+ (id)allocWithZone:(NSZone *)zone
{
return [[self sharedInstance]retain];
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (unsigned)retainCount
{
return NSUIntegerMax; //denotes an object that cannot be released
}
- (void)release
{
//do nothing
}
- (id)autorelease
{
return self;
}
I hope it helps

I highly recommend using the SyntesizeSingleton header file first created by Matt Gallagher.
Find the latest version (that I know about) here:
https://github.com/cjhanson/Objective-C-Optimized-Singleton
It makes creating a singleton dead simple.
Here's an example header:
#import <Foundation/Foundation.h>
#interface Example : NSObject {}
+(Example*)sharedExample;
#end
And the corresponding .m:
#import "FMUser.h"
#import "SynthesizeSingleton.h"
#implementation Example
SYNTHESIZE_SINGLETON_FOR_CLASS(Example);
#end
[Example sharedExample] is created for you. It's pretty sweet.

Related

Objective-C, class identity

I have the following situation, i can't resolve:
#interface Deck : NSObject
#interface MasterDeck : Deck
#interface PlayerDeck : Deck
Inside MasterDeck class, as part of initialization, i call
[self cutDeckImageIntoCards]; // We don't get to execute this method
Call results in an error [PlayerDeck cutDeckImageIntoCards]: unrecognized selector sent to instance
Indeed, PlayerDeck does not have this method .. but why is it being called at all?
After looking at MasterDeck's initialization i added a few debugging statements:
static MasterDeck *gInstance = NULL;
+(MasterDeck *) instance {
#synchronized(self) {
if (gInstance == NULL) {
gInstance = [[self alloc] init];
}
}
return gInstance;
}
-(id) init {
if (gInstance != NULL) {
return gInstance;
}
// MasterDeck
self = [super init];
// PlayerDeck
if (self) {
// Lots of stuff
[self cutDeckImageIntoCards]
// Some more stuff
}
gInstance = self;
return gInstance;
}
Ok, so MasterDeck is PlayerDeck because' Deck thinks it is a PlayerDeck ... Deck confirms
Deck is created as follows:
static Deck *gInstance = NULL;
+(Deck *) instance {
#synchronized(self) {
if (gInstance == NULL) {
gInstance = [[self alloc] init];
}
}
return gInstance;
}
-(id) init {
if (gInstance != NULL) {
return gInstance;
}
self = [super init];
if (self) {
// Do something
}
NSLog(#"Deck thinks it's a %#", [[self class ]description]); // PlayerDeck
gInstance = self;
return gInstance;
}
So, again
#interface Deck : NSObject
Assuming above Singleton Implementation, why would Deck think it's actually a PlayerDeck?
So the way you've written this, if you create the PlayDeck instance first, then the Deck instance is now a PlayDeck.
And then if you go to create the MasterDeck instance, your call to [super init] dutifully returns that previous PlayDeck instance.
So why is Deck a singleton at all? Deck has two subclasses that are singletons, but are you really looking for a singleton Deck also?
At a minimum, you can make this sort of work by not setting gInstance from within each init. Let the class method do that. Just return self from each of the init's. Also, remove the check for gInstance being not null, other Deck's init will always return Deck's instance once you have an instance of Deck.
But beyond that, I would rethink this idea a bit. Hope that helps.
You'll probably want to separate your singleton class from the actual class.
Try implementing it as in this example,
+(id) instance {
static dispatch_once_t pred;
static MasterDeck *sharedInstance = nil;
dispatch_once(&pred, ^{
sharedInstance = [[MasterDeck alloc] init];
});
return sharedInstance;
}
What happens if you replace [[self alloc] init] with [[MasterDeck alloc] init]?
It may be that somehow self is PlayerDeck. To make sure, you could NSLog([self description]) just before calling + alloc.
Edit
I assume that the interesting part of the code you have above is part of the #implementation of MasterDeck. My suggestion would be to try a lot more logging, including determining what super and [self class] are before calling [super init], although these may be misleading...
Also, as a side note, I believe that you should call [self release] in init if you are returning the previously-created instance.
What does the [super init] method look like? Can you step into it, or is it the default initializer?
Edit 2
I think you're doing singletons wrong. If you initialize a PlayerDeck, that would create a singleton in Deck which is an instance of PlayerDeck. Then later, when you initialize a MasterDeck, calling [super init] will return the instance already created by the PlayerDeck.
It looks like you try to be clever, but fact is - often the computer is even smarter. :)
Your deck class caches an instance in gInstance - in fact, it looks like it may store a Deck, a PlayerDeck, or a MasterDeck, depending on what and how you call / instantiate first. After that, this very instance is returned by that init method.
I strongly suggest to get this code clean and readable. I bet there are numerous problems with this code - but your problem is already a good example. Your logic (which should be simple, I guess) can surely be implemented much easier.
Note - I'm not against singletons, but this sort of code stacking is an absolute no-go. It's hard to get more dependency logic into those lines. ;)

Objective C - deallocated variable

I have this static/singelton class that has a member variable.
Everything works just fine, however, when I quit the app, and the come back, that member variable is causing the app to crash.
I tried reinitializing the member variable, but doesn't seem to do the trick.
I am including samples of my code below, has anyone seen this before?
The header (.h) file:
#interface Metrics : NSObject {
Metrics *metrics;
Distance *distance;
}
The implementation (.m) file:
#implementation Metrics
static Metrics *metrics = nil;
+ (Metrics *)sharedInstance {
#synchronized(self) {
if (metrics == nil) {
metrics = [[Metrics alloc] init];
}
}
return metrics;
}
- (id)init {
self = [super init];
if (self) {
}
return self;
}
-(void) setupDistance
{
distance = [[Distance alloc] init];
distance.test; // it dies here after I quit the app and come back
}
And where it is used, AppDelegate.m
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[[Metrics sharedInstance] setupDistance];
}
Thank you,
Tee
When you say "quit the app" you almost certainly mean "send the app to the background." This does not terminate your application. When you become active again, you're leaking distance and assigning a new one. I suspect that something in test is actually the problem.
First, don't access your ivars directly, except in init and dealloc. Use accessors. This will make most of your problems go away.
Second, don't call setupDistance in applicationDidBecomeActive. You mean to call it in applicationDidFinishLaunchingWithOptions:. But better yet, just initialize it during Metrics init. Why have this internal Metrics detail in the app delegate?
applicationDidBecomeActive will get called when it comes back from sleep calling to setup in the distance again. It's wierd that you're calling a property (.test) and not assigning. Is test doing work? Should it be a method? What's it doing?
Also, in a singleton you have to overload quite a few things. Here's a good template for a singleton that I use.
static MySingleton *sharedInstance = nil;
#implementation MySingleton
#pragma mark -
#pragma mark class instance methods
#pragma mark -
#pragma mark Singleton methods
+ (MySingleton*)sharedInstance
{
#synchronized(self)
{
if (sharedInstance == nil)
sharedInstance = [[MySingleton alloc] init];
}
return sharedInstance;
}
+ (id)allocWithZone:(NSZone *)zone {
#synchronized(self) {
if (sharedInstance == nil) {
sharedInstance = [super allocWithZone:zone];
return sharedInstance;  // assignment and return on first allocation
}
}
return nil; // on subsequent allocation attempts return nil
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain {
return self;
}
- (unsigned)retainCount {
return UINT_MAX;  // denotes an object that cannot be released
}
- (void)release {
//do nothing
}
- (id)autorelease {
return self;
}
#end

How to write an Objective-C convenience constructor

I'm trying to add a convenience constructor to my custom object.
Similar to [NSArray arrayWithArray:]
I know it involves a class method that returns an auto released object. I've been googling around but all I can seem to find is the definition of a convenience constructor but not how to write one.
Let's say you have the following:
#class PotatoPeeler : NSObject
- (instancetype)initWithWidget: (Widget *)w;
#end
Then to add a factory method, you'd change it to this:
#class PotatoPeeler : NSObject
+ (instancetype)potatoPeelerWithWidget: (Widget *)w;
- (instancetype)initWithWidget: (Widget *)w;
#end
And your implementation would simply be:
+ (instancetype)potatoPeelerWithWidget: (Widget *)w {
return [[[self alloc] initWithWidget: w] autorelease];
}
Edit: replaced id with instancetype. They are functionally identical, but the latter provides better hints to the compiler about the method's return type.
Generally my approach is the following: first I create a normal initializer method (instance method), then I create a class method that calls the normal initializer. It seems to me Apple uses the same approach most of the time. An example:
#implementation SomeObject
#synthesize string = _string; // assuming there's an 'string' property in the header
- (id)initWithString:(NSString *)string
{
self = [super init];
if (self)
{
self.string = string;
}
return self;
}
+ (SomeObject *)someObjectWithString:(NSString *)string
{
return [[[SomeObject alloc] initWithString:string] autorelease];
}
- (void)dealloc
{
self.string = nil;
[super dealloc];
}
#end

Is this valid code to create a NIB-instantiated singleton?

Assume that I instantiate an object of class MyGreatClass in my NIB (as usual by simply dragging an "Object" to the NIB and settings its class to MyGreatClass).
I want access to that instance anywhere in my codebase, without introducing coupling, i.e. without passing objects around like crazy, and without having an outlet to it in, say, [NSApp delegate]. (The latter would make AppDelegate terribly bulky with time.)
I ask: Is the following considered a good code to accomplish this?
//imports
static MyGreatClass *theInstance = nil;
#implementation MyGreatClass
+ (MyGreatClass *)sharedInstance
{
NSAssert(theInstance != nil, #"instance should have been loaded from NIB");
return theInstance;
}
- (id)init //waking up from NIB will call this
{
if (!theInstance)
theInstance = self;
return theInstance;
}
// ...
If this work as expected, I would after the app is loaded be able to access my instance via sharedInstance.
What do you think?
UPDATE: Hmm, on the second thought, the above init method maybe overkill. This is way simpler to think about:
- (id)init
{
NSAssert(!theInstance, #"instance shouldn't exist yet because only "
#"the NIB-awaking process should call this method");
theInstance = self;
return theInstance;
}
Again, what do you think?
The proper way to create a singleton is to override allocWithZone: to ensure another object cannot be created. Overriding init allows the new object to be created, but not initialized. It is thrown away because the init method simply ignores it and returns the object that has been created already. Here is how I would do it:
+ (MyGreatClass *)sharedInstance {
NSAssert(theInstance != nil, #"instance should have been created from NIB");
return theInstance;
}
+ (MyGreatClass *)allocWithZone:(NSZone *)zone {
if(theInstance) return theInstance;
return [[self alloc] init];
}
- (id)init {
if(theInstance) return theInstance;
if(self = [super init]) {
theInstance = self;
// other initialization
}
return self;
}
- (void)release {}
- (void)dealloc {
return;
[super dealloc]; // Prevent compiler from issuing warning for not calling super
}
I overrode release and dealloc to ensure that the singleton would not be deallocated. If you don't do this, you should retain and autorelease it in the sharedInstance method. If you want to support multithreading, you should also synchronize access to the theInstance variable.

Elegant and 'correct' multiton implementation in Objective C?

Would you call this implementation of a multiton in objective-c 'elegant'? I have programmatically 'disallowed' use of alloc and allocWithZone: because the decision to allocate or not allocate memory needs to be done based on a key.
I know for sure that I need to work with only two instances, so I'm using 'switch-case' instead of a map.
#import "Multiton.h"
static Multiton *firstInstance = nil;
static Multiton *secondInstance = nil;
#implementation Multiton
+ (Multiton *) sharedInstanceForDirection:(enum KeyName)direction {
return [[self allocWithKey:direction] init];
}
+ (id) allocWithKey:(enum KeyName)key {
return [self allocWithZone:nil andKey:key];
}
+ (id) allocWithZone:(NSZone *)zone andKey:(enum KeyName)key {
Multiton **sharedInstance;
#synchronized(self) {
switch (key) {
case KEY_1:
sharedInstance = &firstInstance;
break;
case KEY_2:
sharedInstance = &secondInstance;
break;
default:
[NSException raise:NSInvalidArgumentException format:#"Invalid key"];
break;
}
if (*sharedInstance == nil)
*sharedInstance = [super allocWithZone:zone];
}
return *sharedInstance;
}
+ (id) allocWithZone:(NSZone *)zone {
//Do not allow use of alloc and allocWithZone
[NSException raise:NSObjectInaccessibleException format:#"Use allocWithZone:andKey: or allocWithKey:"];
return nil;
}
- (id) copyWithZone:(NSZone *)zone {
return self;
}
- (id) retain {
return self;
}
- (unsigned) retainCount {
return NSUIntegerMax;
}
- (void) release {
return;
}
- (id) autorelease {
return self;
}
- (id) init {
[super init];
return self;
}
#end
PS: I've not tried out if this works as yet, but its compiling cleanly :)
I find singletons a bad idea and this looks about four times as horrible. The code is quite complex, you can be sure of spending a nice few hours chasing subtle bugs in it and you will probably never feel comfortable about it. That’s no good. You should throw this abomination away and wire your objects together in some other way that doesn’t require so much thinking.
If you like patterns, you can use something akin to Factory pattern to wire your objects. The Factory will take care of creating those two instances and passing them wherever needed. And the Factory will be a lot more simple than Multiton:
#interface Factory : NSObject {
Foo *foo1, *foo2;
}
#end
#implementation Factory
- (id) init {
[super init];
foo1 = [[Foo alloc] init];
foo2 = [[Foo alloc] init];
return self;
}
Of course you don’t have to create both instances at once. You can do anything you like there – cache, lazy load, anything. The point is leaving the Foo lifetime management up to the Factory, separate from the Foo code. Then it gets much easier. ¶ All the other objects that need Foo will be created and wired through Factory and will receive their Foo through a setter:
#implementation Factory
- (id) wireSomeClass {
id instance = [[SomeClass alloc] init];
[instance setFoo:foo1];
[instance setAnotherDependency:bar];
return [instance autorelease];
}
This is all much more straightforward then the code from your question.
Don't override alloc. The problem with overriding alloc to return a previously allocated instance of the class, as you do, is that when +sharedInstance calls [[Multiton alloc] init]... +alloc will return the old instance, then -init will re-initialize it! The best practice is to override -init, doing the cache lookup and calling [self release] before you return the cached instance.
If you're really concerned about the cost of that extra +alloc (it's not much), you also do your cache lookup in +sharedInstance and then ensure that all of your clients access the instance through +sharedInstance to avoid the extra alloc.
Point of order: How do you know that you'll only ever have two instances, or need to have two instances? (Or want to have two instances?) What, exactly, is the point of having a "Multiton"? (And is that even a word?)