2013-02-19 71 views
2

我想写一个主从应用程序,从sqlite数据库获取它的数据。作为这一部分,我试图创建一个帮助类,创建我的数据库的单例实例。我希望它做的就是初始化数据库,然后我可以从应用程序的不同视图中引用它。 我跟着一个教程,这样做在这里:http://www.raywenderlich.com/913/sqlite-101-for-iphone-developers-making-our-app创建一个单身DB辅助类

我得到的教程工作,但现在我试图修改它,以适应我的应用程序,我似乎无法得到它的工作。我没有错误或警告,但是当我在模拟器上运行应用程序时,没有执行任何调试文本。所以它看起来像我的init函数没有执行。我无法弄清楚为什么。 任何人都可以在下面的代码中发现我的问题吗?

LoyaltyProgramDatabase.h

#import <Foundation/Foundation.h> 
#import <sqlite3.h> 

@interface LoyaltyProgramDatabase : NSObject { 
    sqlite3 *_loyaltyProgDB; 
} 

@property (strong, nonatomic) NSString *databasePath; //Path file of our database 
@property (nonatomic) sqlite3 *loyaltyProgDB; //Reference to the database 

+ (LoyaltyProgramDatabase*)loyaltyProgDB; 

@end 

LoyaltyProgramDatabase.m

#import "LoyaltyProgramDatabase.h" 

@implementation LoyaltyProgramDatabase 

static LoyaltyProgramDatabase *_loyaltyProgDB; 

//Create a singleton instance of loyaltyProgDB 
+ (LoyaltyProgramDatabase*)loyaltyProgDB { 
    if (_loyaltyProgDB == nil) { 
     _loyaltyProgDB = [[LoyaltyProgramDatabase alloc] init]; 
    } 
    return _loyaltyProgDB; 
} 

- (id)init { 
    NSLog(@"Inside init function"); 
    if ((self = [super init])) { 

     NSString *docsDir; 
     NSArray *dirPaths; 

     // Get the documents directory 
     dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 

    docsDir = dirPaths[0]; 

    // Build the path to the database file 
    _databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:@"loyaltyProg.db"]]; 

    NSFileManager *filemgr = [NSFileManager defaultManager]; 

    if ([filemgr fileExistsAtPath: _databasePath ] == NO) 
    { 
     const char *dbpath = [_databasePath UTF8String]; 

     if (sqlite3_open(dbpath, &_loyaltyProgDB) == SQLITE_OK) 
     { 
      char *errMsg; 
      const char *sql_stmt = "CREATE TABLE IF NOT EXISTS scoreCard (ID INTEGER PRIMARY KEY AUTOINCREMENT, campaignID INTEGER, merchantName TEXT)"; 

      if (sqlite3_exec(_loyaltyProgDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) 
      { 
       //_status.text = @"Failed to create table"; 
       NSLog(@"Failed to create table"); 
      } 
      sqlite3_close(_loyaltyProgDB); 
     } else { 
      //_status.text = @"Failed to open/create database"; 
      NSLog(@"Failed to open/create database"); 
     } 
    }   
}  
return self; 
} 

- (void)dealloc { 
    sqlite3_close(_loyaltyProgDB); 
} 

@end 
+0

您是否曾经称过[LoyaltyProgramDatabase loyaltyProgDB]? – ColdLogic 2013-02-19 10:24:16

+0

另外,该教程是从大约3年前...非常过时。 RayWenderlich应该有更好的教程。 – ColdLogic 2013-02-19 10:25:08

+0

@ColdLogic不,我从来不会调用'[LoyaltyProgramDatabase loyaltyProgDB]',因为我的理解是没有必要,因为数据库在应用程序启动时自动在' - (id)init'函数中启动。 – Roardog 2013-02-19 10:46:06

回答

0

试试这个:

+ (id)allocWithZone:(NSZone *)zone 
{ 
    return [self loyaltyProgDB]; 
} 

+ (LoyaltyProgramDatabase*)loyaltyProgDB 
{ 
    static BNRImageStore *loyaltyProgDB = nil; 
    if (!loyaltyProgDB) { 
     // Create the singleton 
     loyaltyProgDB = [[super allocWithZone:NULL] init]; 
    } 
    return loyaltyProgDB; 
} 

- (id)init { 
    self = [super init]; 
    if (self) { 

     NSString *docsDir; 
     NSArray *dirPaths; 

     // Get the documents directory 
     dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 

     docsDir = dirPaths[0]; 

     // Build the path to the database file 
     _databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:@"loyaltyProg.db"]]; 

     NSFileManager *filemgr = [NSFileManager defaultManager]; 

     if ([filemgr fileExistsAtPath: _databasePath ] == NO) 
     { 
      const char *dbpath = [_databasePath UTF8String]; 

      if (sqlite3_open(dbpath, &_loyaltyProgDB) == SQLITE_OK) 
      { 
       char *errMsg; 
       const char *sql_stmt = "CREATE TABLE IF NOT EXISTS scoreCard (ID INTEGER PRIMARY KEY AUTOINCREMENT, campaignID INTEGER, merchantName TEXT)"; 

       if (sqlite3_exec(_loyaltyProgDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) 
       { 
        //_status.text = @"Failed to create table"; 
        NSLog(@"Failed to create table"); 
       } 
       sqlite3_close(_loyaltyProgDB); 
      } else { 
       //_status.text = @"Failed to open/create database"; 
       NSLog(@"Failed to open/create database"); 
      } 
     } 
    } 
    return self; 
} 
+0

这不会给我任何错误或警告,但我的NSLog仍然没有显示出来。 – Roardog 2013-02-19 10:57:40

+0

您必须调用loyaltyProgDB创建并初始化单例实例。 也就是说 LoyaltyProgramDatabase * loyaltyProgDBSingleToneInstance = [LoyaltyProgramDatabase loyaltyProgDB]; – jackdev23 2013-02-19 17:47:23

0

如果您还没有写一行代码,说[[LoyaltyProgramDatabase alloc] init][LoyaltyProgramDatabase loyaltyProgDB],然后你的init函数从来没有得到c alled。

当您启动应用程序时,不会自动调用init。自动调用任何init函数时,如果在nib/xib/storyboard文件中有一个UI元素,并且该应用程序使用各种初始化函数创建元素,但从未使用您自己的init函数。但是对于你写的东西,为了初始化数据库对象,你需要自己调用init函数。

在你的应用程序代理,该didFinishLaunching作用下,把这个行:

[LoyaltyProgramDatabase loyaltyProgDB]; 

这是不是的方式真正跟上时代的单例模式。这实际上是一个懒惰的加载函数。如果你想要一个更安全的单身人士,请使用此代码。

+(id)sharedInstance { 
    static dispatch_once_t pred = 0; 
    __strong static id _sharedObject = nil; 
    dispatch_once(&pred, ^{ 
    _sharedObject = [[self alloc] init]; 
    }); 
    return _sharedObject; 
} 

这将确保数据库只有一次初始化并且是线程安全的。要创建/使用单身人士,代码将从以上变为

[LoyaltyProgramDatabase sharedInstance]