ios singleton类崩溃了我的应用程序

我有一个单例模式的问题。

我已经阅读了以下有关单例类的教程,并创建了自己的类。 http://www.galloway.me.uk/utorials/singleton-classes/ http://www.johnwordsworth.com/2010/04/iphone-code-snippet-the-singleton-pattern/

我第一次构建和运行应用程序,它的工作原理应该如此。 没问题! 但是,当我重建应用程序时,单例类不再正常工作。 第一个init就像应该的那样工作,但是当我点击按钮后再次调用它时会崩溃我的应用程序。

我的单身课程:

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]; } 

当我在构建界面时调用以下代码时,应用程序会创建单例:

 BPManager *manager = [BPManager bpManager]; [manager initDatabase:@"database.db"]; 

注意:此时我也可以从其他文件创建对该类的引用。 但是,当我点击一个按钮时,它似乎松开了他的参考。

但是,当单击一个按钮时,会输出以下代码:

 BPManager *manager = [BPManager bpManager]; int count = [manager getQuestions]; 

该应用程序应该获取sharedInstance。 这样做,只有参数(如dbPath)不可访问。 这是为什么?

编辑:

经过一番研究,我把方法改为:

 + (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; } 

但问题没有解决

怎么样

 @interface BPManager : NSObject @property (nonatomic, copy) NSString *dbName; @property (nonatomic, assign) int questions; -(id) initWithDBName:(NSString*) dbName { @end #import "BPManager.h" @implementation BPManager @synthesize dbName=_dbName, questions; +(BPManager *)singleton { static dispatch_once_t pred; static BPManager *shared = nil; dispatch_once(&pred, ^{ shared = [[BPManager alloc] initWithDBName:@"database.db"]; }); return shared; } -(id) initWithDBName:(NSString*) dbName { self = [super init] if (self) self.dbName = dbName; return self; } -(void)dealloc { [_dbName release]; [super dealloc]; } @end BPManager *manager = [BPManager singleton]; int count = [manager questions]; 

静态对于实现文件是私有的,但没有理由在单例方法之外甚至可以访问它。 init使用默认实现覆盖默认实现,因此它没用。 在Objective-C中,使用var name(count)命名getter,而不是getCount。 初始化类两次会导致未定义的行为。 当您已经使用dispatch_once时,无需同步或检查if == nil,请参阅单身护理和喂养 。 NSString应始终使用copy而不是@property中的保留。 你不需要dealloc,因为这将在你的应用程序运行时永远保持活跃状态​​,但它就是你想要将这个类用作非单例的情况。 你可能也很好,这个class级在你的代表中是一个ivar而不是单身,但你可以两种方式。

我不确定它是否是(完整)答案,但一个主要缺陷是你在类方法中使用实例变量( selfsuper ), +(id)bpManager ; 我真的很惊讶它让你编译它。 将@synchronized(self)更改为@synchronized(sharedMyManager) ,将[[super alloc...] init]更改为[[BPManager alloc...] init] 。 写这篇文章只是让我意识到问题看起来像是在实例化为超类的对象上访问子类化方法,但是应该在调度中被覆盖。 你不应该真的只需要其中一个,为什么这样双启动? (当我们在那里时,这是一个内存泄漏 – 在if()初始化,然后在关闭时覆盖而不释放它。)

Jano的解决方案必须运作良好。 我也用这种方式创建单例对象。 我没有任何问题。

对于你的代码,我认为如果你使用@synchronized(这不是必要的,因为Jano说你有dispatch_once_t),你不应该在@synchronized中调用return。

 + (BPManager *) bpManager { @synchronized(self) { if(sharedMyManager == nil) { static dispatch_once_t pred; // Lock dispatch_once(&pred, ^{ // This code is called at most once per app sharedMyManager = [[BPManager alloc] init]; }); } } return sharedMyManager; }