More than 1 year has passed since last update.

はじめに

Swiftでクイズアプリを作る際に問題管理をSQLiteで行いため、Objective-C時代に利用したライブラリFMDBを使うことにした。

環境

使用したもの

Xcode 6.3.1
iOS 8.3
FMDB Ver2.5
Lita

導入

まず、プロジェクトを作成後に

スクリーンショット_2015_05_19_午後8_36.png

FMDBをDL

fmdb-master.png

fmdbをプロジェクトを開いているXcodeにドラッグアンドドロップ

スクリーンショット_2015_05_19_午後8_41.png

Create groupsを選択して追加

次に、NewFile→Hedder Fileを選択

スクリーンショット_2015_05_19_午後8_47.png

ファイル名を

プロジェクト名-Bridging-Header.h

で作成

ファイルを開くと

test-Bridging-Header_h_—_Edited_1.png

このようになっているので、FMDBをインポートしてあげる

test-Bridging-Header_h_—_Edited.png

#import "FMDatabase.h"
#import "FMResultSet.h"
#import "FMDatabaseAdditions.h"
#import "FMDatabaseQueue.h"
#import "FMDatabasePool.h"

ターゲットの

Build Setting → Swift Compiler - Code Generation → Objective-C Bridging Header

を選択して以下の用に記述

プロジェクト名/プロジェクト名-Bridging-Header.h

test_xcodeproj.png

これで、使えるはずです。

使い方

ターミナルでdbをつくる

sqlite3 データベース名

ターミナル_—_sqlite3_—_80×24.png

sqlite> .schema

.schemaと入力するとファイルが生成されるので

Litaで開いてテーブル追加

データ入力を終えた、dbをプロジェクトにドラッグアンドドロップ

スクリーンショット_2015_05_19_午後9_13.png

以下のコードでビルド後に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の書き方

こちらの記事を参考にしてもらえると良いと思います。