I have a problem with an singleton pattern.
I have read the following tutorials about singleton classes and have created my own.
http://www.galloway.me.uk/utorials/singleton-classes/
http://www.johnwordsworth.com/2010/04/iphone-code-snippet-the-singleton-pattern/
The first time i build & run the app it works like it should. No problems at all!
But when i rebuild the app the singleton class does not work properly anymore. The first init works like it should but when i call it again after a button click it crashes my app.
My singleton class:
BPManager.h
@interface BPManager : NSObject {
NSString *dbPath;
}
@property (nonatomic, retain) NSString *dbPath;
+ (id)bpManager;
- (void)initDatabase:(NSString *)dbName;
- (int)getQuestions;
@end
BPManager.m
static BPManager *sharedMyManager = nil;
@implementation BPManager
@synthesize dbPath;
- (void)initDatabase:(NSString *)dbName
{
dbPath = dbName;
}
-(int)getQuestions
{
NSLog(@"getQuestions");
}
- (id)init {
if ((self = [super init])) {
}
return self;
}
+ (BPManager *) bpManager {
@synchronized(self) {
if(sharedMyManager != nil) return sharedMyManager;
static dispatch_once_t pred; // Lock
dispatch_once(&pred, ^{ // This code is called at most once per app
sharedMyManager = [[BPManager alloc] init];
});
}
return sharedMyManager;
}
- (void)dealloc {
[dbPath release];
[super dealloc];
}
When i call the following code when building my interface, the app creates the singleton:
BPManager *manager = [BPManager bpManager];
[manager initDatabase:@"database.db"];
Note: At this point i can create references to the class from other files as well. But when i click on a button it seems to loose his references.
But when a button is clicked, the following code is ecexuted:
BPManager *manager = [BPManager bpManager];
int count = [manager getQuestions];
The app should get the sharedInstance. That works, only the parameters (like dbPath) are not accessible. Why is that?
Edit:
after some research, i have changed the method to:
+ (BPManager *) bpManager {
@synchronized(self) {
if(sharedMyManager != nil) return sharedMyManager;
static dispatch_once_t pred; // Lock
dispatch_once(&pred, ^{ // This code is called at most once per app
sharedMyManager = [[BPManager alloc] init];
});
}
return sharedMyManager;
}
But the problem is not solved
How about
The static is private to the implementation file but no reason it should be even accessible outside the singleton method. The init overrides the default implementation with the default implementation so it’s useless. In Objective-C you name the getter with the var name (count), not getCount. Initializing a class twice causes an undefined behaviour. No need to synchronize or check for if==nil when you are already using dispatch_once, see Care and Feeding of Singletons. NSString should always use copy instead retain in @property. You don’t need the dealloc because this is going to be active forever while your app is running, but it’s just there in case you want to use this class as a non singleton . And you probably are as good with this class being an ivar in your delegate instead a singleton, but you can have it both ways.