我正在尝试编写一个Master-Detail应用程序,它从sqlite数据库中获取数据。作为其中的一部分,我正在尝试创建一个帮助程序类,它创建我的数据库的单例实例。我想要它做的就是初始化数据库,以便我可以从应用程序的不同视图中引用它。 我按照教程执行了此操作:http://www.raywenderlich.com/913/sqlite-101-for-iphone-developers-making-our-app
我得到了教程,但是现在我正在尝试修改它以适应我的应用程序,我似乎无法让它工作。我没有错误或警告,但是当我在模拟器上运行应用程序时,我执行的调试文本都没有。所以它看起来像我的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 :(得分: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;
}
答案 1 :(得分:0)
如果您还没有编写一行代表[[LoyaltyProgramDatabase alloc] init]
或[LoyaltyProgramDatabase loyaltyProgDB]
的代码,那么您的init
函数永远不会被调用。
启动应用时,系统不会自动调用init
。自动调用任何init
函数的唯一情况是,如果您在nib / xib / storyboard文件中有UI元素,并且应用程序使用各种初始化函数创建元素,但从不使用您自己的init
函数。但是对于像你所写的那样,要初始化数据库对象,你需要自己调用init
函数。
在您的app委托中,在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]