SQLite3を使うよ その1 データベース準備
CoreDataを一夜漬けでなんとかしてみようかとも思ったのですが、サーバーに送信するためにデータを保存しつつ、それを定期的に非同期で上げていくのにCoreDataみたいな大掛かりな永続化の仕組みは要らないよなと思い直し、SQLiteだけで処理することにしました。
プロジェクトにライブラリを追加
まずはSQLiteを使う為のライブラリをプロジェクトに追加します。Project Navigatorのプロジェクトアイコンをクリックして、[Build Phases]のライブラリ追加のところで+を押して"libsqlite3.dylib"を追加。次に[Build Settings]のLinkingのOther Linker Flagsに "-lsqlite3"を追加します。
データベースファイルを用意
ターミナルで
$ sqlite3 hogehoge.sqlte
というコマンドを実行して、SQLiteのコンソールに入り、SQLのDDLを使って必要なテーブルを定義します。たとえば↓な感じ。
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);
}
}
これで、データベースを使う準備ができました。