22
20

More than 5 years have passed since last update.

SwiftでFMDBを利用する

Last updated at Posted at 2015-05-19

はじめに

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

環境

使用したもの

Xcode 6.3.1
iOS 8.3
[FMDB Ver2.5][1]
[Lita][2]

導入

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

スクリーンショット_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の書き方

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

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

22
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
20