読者です 読者をやめる 読者になる 読者になる

sos の 作業メモ

プログラミングや英会話学習、マイルや旅行、日常生活など。最近はWebFormなASP.NETのお守りがお仕事です。

日々の生活にhappyをプラスする|ハピタス Gポイント

SQLite3を使うよ その1 データベース準備

iOS Objective-C

CoreDataを一夜漬けでなんとかしてみようかとも思ったのですが、サーバーに送信するためにデータを保存しつつ、それを定期的に非同期で上げていくのにCoreDataみたいな大掛かりな永続化の仕組みは要らないよなと思い直し、SQLiteだけで処理することにしました。

プロジェクトにライブラリを追加

まずはSQLiteを使う為のライブラリをプロジェクトに追加します。Project Navigatorのプロジェクトアイコンをクリックして、[Build Phases]のライブラリ追加のところで+を押して"libsqlite3.dylib"を追加。次に[Build Settings]のLinkingのOther Linker Flagsに "-lsqlite3"を追加します。

データベースファイルを用意

ターミナルで

$ sqlite3 hogehoge.sqlte

というコマンドを実行して、SQLiteのコンソールに入り、SQLDDLを使って必要なテーブルを定義します。たとえば↓な感じ。

CREATE TABLE hoge (id INTEGER PRIMARY KEY, data TEXT);

データベースファイルをプロジェクトに追加

できあがったデータベースファイルをfinderでXcodeのプロジェクトにドラッグして追加。これでNSBundleとしてプログラムからコピーできるようになります。

アプリ起動時にDocumentディレクトリにコピー

Bundleなファイルは読み込み専用となりますので、起動時にデータベースファイルをDocumentディレクトリにコピーし、データの読み書きはそちらのファイルを対象とするようにします。↓のようなメソッドを作って、application:didFinishLaunchingWithOptions: あたりで実行すればOKです。

+ (NSString *)copyDatabaseToDocuments:(NSString*)filename
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docRoot = [paths objectAtIndex:0];    // document root
    NSString *filePath = [docRoot stringByAppendingPathComponent:filename];

    if(![fileManager fileExistsAtPath:filePath]){   //  ファイルが無ければコピー
        NSError *error = nil;
        NSString *bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:filename];

        [fileManager copyItemAtPath:bundlePath toPath:filePath error:&error];  //  アプリバンドル内のDBファイルを、doc rootにコピー
        if(error){
            return nil;
        }
    }
    return filePath;
}

データベースオープン/クローズ

いよいよデータベースのオープンとクローズ。わざわざメソッドにする必要もありませんが、なんとなく準備しておきます。

+ (sqlite3*)openDatabase:(NSString*)dbFilePath
{
    sqlite3* database;

    if(dbFilePath && sqlite3_open([dbFilePath UTF8String], &database) == SQLITE_OK){
        return database;
    }else{
        return NULL;
    }
}

+ (void)closeDatabase:(sqlite3*)database
{
    if(database){
        sqlite3_close(database);
    }
}

これで、データベースを使う準備ができました。

その2へ続く