はじめに
Swiftでクイズアプリを作る際に問題管理をSQLiteで行いため、Objective-C時代に利用したライブラリFMDBを使うことにした。
環境
使用したもの
Xcode 6.3.1
iOS 8.3
FMDB Ver2.5
Lita
導入
まず、プロジェクトを作成後に
FMDBをDL
fmdbをプロジェクトを開いているXcodeにドラッグアンドドロップ
Create groupsを選択して追加
次に、NewFile→Hedder Fileを選択
ファイル名を
プロジェクト名-Bridging-Header.h
で作成
ファイルを開くと
このようになっているので、FMDBをインポートしてあげる
#import "FMDatabase.h"
#import "FMResultSet.h"
#import "FMDatabaseAdditions.h"
#import "FMDatabaseQueue.h"
#import "FMDatabasePool.h"
ターゲットの
を選択して以下の用に記述
プロジェクト名/プロジェクト名-Bridging-Header.h
これで、使えるはずです。
使い方
ターミナルでdbをつくる
sqlite3 データベース名
sqlite> .schema
.schemaと入力するとファイルが生成されるので
Litaで開いてテーブル追加
データ入力を終えた、dbをプロジェクトにドラッグアンドドロップ
以下のコードでビルド後にDocumentsフォルダの中にdbがなかったら、コピーするようにしている
setSqlite()をViewDidLoadなどで呼び出してもらう
func setPath()->(String){
// /Documentsまでのパスを取得
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask, true)
// <Application>/Documents/test.db というパスを生成
let _path = paths[0].stringByAppendingPathComponent("test.db")
return _path
}
func setSqlite(){
if NSFileManager.defaultManager().fileExistsAtPath(setPath()) == false {
//ファイルがない場合はコピー
let defaltDBPath :String = NSBundle.mainBundle().pathForResource("test.db", ofType:nil)!
NSFileManager.defaultManager().copyItemAtPath(defaltDBPath, toPath: setPath(), error: nil)
if NSFileManager.defaultManager().fileExistsAtPath(setPath()) == false {
//error
println("Copy error = " + defaltDBPath)
}
}else{
println("DB file OK")
}
}
sqlを以下のように記述し値を取得しました。
let db = FMDatabase(path: setPath())
let quiz_sql = "SELECT * FROM quiz_tb where id = \(qNum);"
db.open()
let quiz_results = db.executeQuery(quiz_sql, withArgumentsInArray: nil)
while quiz_results.next() {
// カラム名を指定して値を取得する方法
question = quiz_results.stringForColumn("question") //questionにStringでquestionを代入
answer = quiz_results.stringForColumn("answer")
commentary = quiz_results.stringForColumn("commentary")
}
db.close()
問題点
この記述だと、大本のデータを編集してプロジェクトに上書きコピーした場合
すでに、実機やエミュレータにdbがあるためコピーされない。
一度アプリをアンインストールしてからビルドし直す必要がある。
解決策として
NSFileManager.defaultManager().removeItemAtPath(setPath(), error: nil)
let defaltDBPath :String = NSBundle.mainBundle().pathForResource("test.db", ofType:nil)!
NSFileManager.defaultManager().copyItemAtPath(defaltDBPath, toPath: setPath(), error: nil)
ファイルがあるかないかの判定で、あったらRemoveしてから追加するように記述することで解決しました。
その他Sqlの書き方
こちらの記事を参考にしてもらえると良いと思います。