2

我正在尝试编写一个从 sqlite 数据库中获取数据的 Master-Detail 应用程序。作为其中的一部分,我正在尝试创建一个帮助类来创建我的数据库的单例实例。我想做的就是初始化数据库,这样我就可以从应用程序的不同视图中引用它。我在这里遵循了一个教程: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

忠诚度计划数据库.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
4

2 回答 2

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;
}
于 2013-02-19T10:39:23.097 回答
0

如果你没有写一行代码[[LoyaltyProgramDatabase alloc] init]or [LoyaltyProgramDatabase loyaltyProgDB],那么你的init函数永远不会被调用。

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]
于 2013-02-19T15:46:55.987 回答