I have a following code in my singleton class
static MySingleton *gManager;
+(void)initialize
{
if(self == [MySingleton class])
{
gManager = [[MySingleton alloc] initWithServices:[[MyServices alloc] init]];
}
}
+(MySingleton *)sharedInstance
{
return (gManager);
}
Unfortunately, during the unit tests I see that gManager is an instance of type SenTestCaseRun. I cant seem to figure out why?
So a call like
[[MySingleton sharedInstance] myFunction];
results in an error that myFunction is an unknown selector although it exists in the MySingleton class.
It is of type SenTestCaseRun because I checked using NSStringFromClass function.
Any pointers? Already banged my head for 3-4 hours on this :(.
it may be better to just put the initialization code inside the shared instance method
+(MySingleton *)shared
{
static MySingleton *sharedInstance = nil;
if(sharedInstance == nil){
sharedInstance = [[MySingleton alloc] init];
}
return sharedInstance;
}
also in your code you are comparing an object to a class which will never be true instead of comparing [self class] to [MySingleton class].
Put a breakpoint in +initialize to make sure this variable is set correctly. If that doesn't explain it, use a watchpoint on it to see who's modifying it.
Related
I'm trying to create a singleton. This group of code is meant to establish a settingsMAnager singleton.
Im trying to allocate it but keep throwing an error
Its throwing the error no visible # interface with NSObject.
Declares the selector 'alloc'
Can someone see what's wrong?
Thanks in advance!
//In my .h file I have
+(settingsManager*)getInstance;
-(void)printSettings;
//In My .m file is----
static settingsManager *theInstance = nil;
//Instance Method
+(settingsManager*)getInstance
{
(theInstance == nil)
{
[[self alloc] init];//Im getting "expression result unused" here
}
return theInstance;
}
-(id)alloc
{
theInstance = [super alloc];<------//getting the big error here
return theInstance;
}
-(id)init
{
if (self = [super init])
{
}
return self;
}
(void)printSettings
{
NSLog(#"Hello");
}
You should never subclass the alloc method. Below is the code to use a singleton:
+ (instancetype)sharedInstance {
static SettingsManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[settingsManager alloc] init];
});
return sharedInstance;
}
And if you're interested in some more reading, I suggest you this link.
I'd also suggest you to read the recommended coding guidelines for objective-c.
instancetype
instancetype is a contextual keyword that can be used as a result type to signal that a method returns a related result type. instancetype, unlike id, can only be used as the result type in a method declaration. More details here.
dispatch_once
As explained here, dispatch_once() is synchronous and allows you to execute a piece of code only once.
This is not the right way to implement a singleton. There are a number of unidiomatic and potentially risky bits in your implementation. However, this error is coming from the fact that alloc is a class method, not an instance method as you've written it here.
I've created a simple singleton class to hold static data for my projects.
The first time I access this singleton is onEnter method in my Cocos2d scene. However when I try to access it again later in another method (same scene) this singleton is already released. I'm confused, how do I keep my singleton from being deallocated?
Here's my singleton's interface part:
#import <Foundation/Foundation.h>
#interface OrchestraData : NSObject
+(OrchestraData *)sharedOrchestraData;
#property (retain, readonly) NSArray *animalNames;
#end
Implementation:
#import "OrchestraData.h"
#implementation OrchestraData
#synthesize animalNames = animalNames_;
+(OrchestraData*)sharedOrchestraData
{
static dispatch_once_t pred;
static OrchestraData *_sharedOrchestraData = nil;
dispatch_once(&pred, ^{ _sharedOrchestraData = [[OrchestraData alloc] init]; });
return _sharedOrchestraData;
}
-(id)init {
if (self = [super init]) {
animalNames_ = [NSArray arrayWithObjects:#"giraffe", #"giraffe", #"giraffe", #"giraffe", nil];
}
return self;
}
#end
I'm using my singleton this way:
[[OrchestraData sharedOrchestraData] animalNames];
Update:
I took a fresh look into it with NSZombies enabled, it appears as if my NSArrays were released, not the singleton itself. What do I do?
You must implement your singleton in this way:
1) in .h file of your Singleton Class:
+ (SingletonClass *)instance;
2) in .m file:
+ (SingletonClass *)instance {
static SingletonClass* instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
//your init code here
});
return instance;
}
If you want to call your singleton, just call [SingletonClass instance].
If your are interesting what is "dispatch_once_t", read about Grand Central Dispatch:
http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html
RE Update:
Your NSArray deallocates because you're using the autorelease initializer arrayWithObjects and you assign it directly to the ivar animalNames_. Therefore it is not retained.
To fix this, assign the array to the property:
self.animalNames = [NSArray arrayWithObjects:#"giraffe", #"giraffe", #"giraffe", #"giraffe", nil];
Btw, under ARC this wouldn't have been an issue since the ivar would have been a strong (retaining) reference. I don't get tired encouraging anyone to switch to ARC. It's been available for well over a year now and there's absolutely no point in using MRC code anymore! It really pains me to see how developers still don't use the easier, faster, and straightforward option. (rant off) :)
You setup a pointer wherever you need it.
-(void)someMethod {
MySingleton *singleton = [MySingleton sharedSingleton];
singleton.data = YES; //dumb example to show you did something...
}
-(void)someOtherMethod {
MySingleton *singleton = [MySingleton sharedSingleton]; //You have to create a new pointer...
singleton.data = NO; //another dumber example to show you did something...
}
Note: this assumes that you have created a singleton the same way I have... your code might be different therefore causing my answer not to apply...
You need to overwrite the below method inside your singleton class, because in your program, if someone has initialised [[SingletonClass alloc] init] then singleton will have another instance and release it will cause an error.
+ (id)allocWithZone:(NSZone *)zone{
return [[self SingletonClass] retain];
}
- (id)copyWithZone:(NSZone *)zone{
return self;
}
- (id)retain{
return self;
}
Consider this code:
+(id)sharedInstance
{
static dispatch_once_t pred;
static MyClass *sharedInstance = nil;
dispatch_once(&pred, ^{
sharedInstance = [[MyClass alloc] init];
});
return sharedInstance;
}
If I follow this singleton design pattern I can make the following assumptions:
The allocation and initialization will only be executed once thanks
to GCD.
The sharedInstance class variable can only be accessed from
within this implementation and shared among the class regardless of the instance.
First time I create the instance I would do something like:
MyClass *something = [MyClass sharedInstance];
my question is, If I call the previews code again but like this:
MyClass *somethingOther = [MyClass sharedInstance];
I can only think of one outcome.
Outcome:
static MyClass *sharedInstance = nil;
Makes sharedInstance class variable point to nil and a nil is returned so somethingOther will be nil.
But I thought that what was supposed to happen in a singleton is that the shared instance would be returned instead.
Now consider this code:
+ (MotionManagerSingleton*)sharedInstance {
static MotionManagerSingleton *_sharedInstance;
if(!_sharedInstance) {
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedInstance = [[super allocWithZone:nil] init];
});
}
return _sharedInstance;
}
+ (id)allocWithZone:(NSZone *)zone {
return [self sharedInstance];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
Here the
static MotionManagerSingleton *_sharedInstance;
Doesnt set my variable to nil, but i thought that all object pointers are initialized to nil by default.
My question is, how are these class methods returning the "sharedInstance"?
Thanks
One. Non-initialized pointers are non-initialized.
static MotionManagerSingleton *_sharedInstance;
won't make your MotionManagerSingleton point to nil. It will point to an undefined (garbage) location.
Two. Variables declared static are initialized only once (yes, the syntax is a bit inconsistent with the semantics), so your first implementation won't null out the returned shared instance. That's a perfectly fine implementation.
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. ;)
I'm trying to write a class that I can subclass to have an instant singleton. Here's what I have so far. It works until one of its subclasses calls another via sharedInstance which causes a huge loop that eventually runs out of memory.
Any ideas?
static NSMutableDictionary *sharedInstances = nil;
#implementation Singleton
+ (Singleton*)sharedInstance
{
[Singleton initSharedInstances];
Class myClass = [self class];
Singleton * sharedInstance = [sharedInstances objectForKey:myClass];
#synchronized(myClass)
{
if (sharedInstance == nil)
{
sharedInstance = [[myClass alloc] init];
[sharedInstances setObject:sharedInstance forKey:myClass];
}
}
return sharedInstance;
}
+ (void) initSharedInstances
{
if (sharedInstances == nil)
{
sharedInstances = [[NSMutableDictionary alloc] init];
}
}
#end
Why are you bothering with all this? If you're trying to enforce singleton behavior in the superclass by overriding -retain, -release, -retainCount, and +allocWithZone: then you're doing something completely unnecessary. Far more simple is just to provide a +sharedInstance method and do nothing else. If the user really wants to call +alloc/-init, they can, it just won't do them much good. For examples of this type of singleton in the frameworks, look at NSUserDefaults and NSFileManager (though in the case of the latter, these days Apple actually recommends you ignore the shared instance and alloc/init your own instances of NSFileManager).
In order to do this simple shared instance stuff, all you have to do is, in the singleton class, implement the following:
+ (id)sharedInstance {
static MyClass sharedInstance;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
//sharedInstance = [[MyClass alloc] init];
sharedInstance = [MyClass alloc];
sharedInstance = [sharedInstance init];
});
return sharedInstance;
}
I'm trying to write a class that I can subclass to have an instant singleton. Here's what I have so far. It works until one of its subclasses calls another via sharedInstance which causes a huge loop that eventually runs out of memory.
This sounds like you are describing mutual-recursion. If subclass1 calls subclass2 and subclass2 calls subclass1 then you need to break the loop somewhere, just as with simple self-recursion.
Your sharedInstance itself should not cause infinite recursion unless the init method you invoke itself invokes sharedInstance...