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

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
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]またはというコード行を記述していない場合は[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 に答える