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.