2011-04-29 246 views
0

我使用以下语句调用以下代码:SQLiteDB * db = [[[SQLiteDB alloc] init] autorelease];Singleton未正确初始化

问题是“sharedSQLiteDB”没有被调用,而是“allocWithZone”,因此“checkIfDatabaseExists”没有被调用,这是数据库创建的地方。

我不明白为什么...(即我究竟做错了什么?)

#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 
} 

回答

0

它不执行你的+ (SQLiteDB *) sharedSQLiteDB方法,因为你没有实际调用该方法的任何地方。

正如您所见,当您拨打[[SQLiteDB alloc] init]时,将调用allocWithZone方法。

将您的呼叫改为SQLiteDB *db = [SQLiteDB sharedSQLiteDB],在这种情况下将调用您的checkIfDatabaseExists方法。但是,如果[[SQLiteDB alloc] init]在其他地方被调用,那么checkIfDatabaseExists方法调用仍将被跳过。

也许考虑将checkIfDatabaseExists方法转换为init方法,以便它将用于您的单例方法和allocWithZone

+0

非常感谢......现在正在工作......我感谢大家的输入...... – SpokaneDude 2011-04-29 17:41:19

0

老实说我没有看到任何错误... 但是我发布了我用来创建单例的代码。这是从一个来源,现在我不记得链接...这不是我的代码。

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

我希望它能帮助

1

在Singleton模式的使用模式应该是:

SQLiteDB* db = [SQLiteDB sharedSQLiteDB]; 

他们的方式,你在呼唤它不适合singelton模式。所有的访问都应该通过你的sharedSQLiteDB消息。

换句话说,您不应该通过典型的Cocoa模式(SQLiteDB * db = [[[SQLiteDB alloc] init] autorelease];初始化;不正确并且存在问题)。

在使用默认的语言初始化模式(ObjC的alloc/init或C++的默认构造函数)的单例中,应该生成编译时错误消息,因为应该保护构造函数/ init方法。

查看Wikipedia条目。请参阅Design Pattern C++圣经。甚至有一个版本Cocoa

祝你好运。

0

我强烈建议使用由Matt Gallagher首先创建的SyntesizeSingleton头文件。

找到最新版本(我知道)在这里:

https://github.com/cjhanson/Objective-C-Optimized-Singleton

它使创建一个单独死的简单。

下面是一个例子标题:

#import <Foundation/Foundation.h> 
@interface Example : NSObject {} 
+(Example*)sharedExample; 
@end 

以及相应的.m:

#import "FMUser.h" 
#import "SynthesizeSingleton.h" 
@implementation Example 
SYNTHESIZE_SINGLETON_FOR_CLASS(Example); 
@end 

[Example sharedExample]为您创建。这很漂亮。