SwiftでFMDBを利用する

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

# 環境
## 使用したもの
Xcode 6.3.1
iOS 8.3
[FMDB Ver2.5][1]
[Lita][2]

# 導入

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

![スクリーンショット_2015_05_19_午後8_36.png](https://qiita-image-store.s3.amazonaws.com/0/60014/249989bd-4813-0174-acf2-05f8adab7956.png)

FMDBをDL

![fmdb-master.png](https://qiita-image-store.s3.amazonaws.com/0/60014/632f85e4-17dc-c708-fdd1-c08867f41077.png)

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

![スクリーンショット_2015_05_19_午後8_41.png](https://qiita-image-store.s3.amazonaws.com/0/60014/9b4e6d3d-0883-3759-88e3-e196981b5370.png)

Create groupsを選択して追加

次に、NewFile→Hedder Fileを選択

![スクリーンショット_2015_05_19_午後8_47.png](https://qiita-image-store.s3.amazonaws.com/0/60014/f77d0112-e42c-3ded-393f-bbdda0d0aef7.png)

ファイル名を

```
プロジェクト名-Bridging-Header.h
```
で作成

ファイルを開くと

![test-Bridging-Header_h_—_Edited_1.png](https://qiita-image-store.s3.amazonaws.com/0/60014/c34a7fec-7f66-0380-876b-a005de8b6eb5.png)

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

![test-Bridging-Header_h_—_Edited.png](https://qiita-image-store.s3.amazonaws.com/0/60014/e363f83b-39b2-9ba8-fe11-45577c0b4d5e.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](https://qiita-image-store.s3.amazonaws.com/0/60014/40c4d38c-4255-4be5-87ba-6c17066e2608.png)

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

# 使い方

ターミナルでdbをつくる

```
sqlite3 データベース名
```
![ターミナル_—_sqlite3_—_80×24.png](https://qiita-image-store.s3.amazonaws.com/0/60014/7839f479-84e9-976e-1e05-1497da207b07.png)

```
sqlite> .schema
```

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

Litaで開いてテーブル追加

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

![スクリーンショット_2015_05_19_午後9_13.png](https://qiita-image-store.s3.amazonaws.com/0/60014/75e11b92-0769-34b4-a980-153f75ab8989.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の書き方

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

[1]:https://github.com/ccgus/fmdb
[2]:http://www.dehats.com/drupal/?q=node/58
[3]:http://blogios.stack3.net/archives/2610