2017年1月21日土曜日

iOS アプリに Swift Realm を導入する

アプリ開発系の話が続きますが、書いておかないと忘れてしまうので。

今回はiOS アプリで Swift Realm を導入する方法です。



Swift Realmって何?


Realm は組み込み用DB(データベース)です。

iOS と android のどちらでも使えます。

iOS には Objective C 版と Swift 版があり、Swift 版が Swift Realm。



ただし、DBと言ってもSQL文などの高度な検索言語は使えません。

その代わり、クラスのメンバ変数がそのままDBカラムになっていたり、

オブジェクトがDBのレコードを表してしていたりします。

そのため、クラス定義でDBスキーマを定義し、

オブジェクト操作がレコード操作になるなど、

データベースの知識がなくても組み込みDBを扱うことができます。



ここまでで「は?宇宙語?」と思った方は気にせず先に進んでください。





Cocoa Pods




Swift Realm を導入する前に、まずは Cocoa Pods を入れます。

Cocoa Pods は Mac のライブラリ管理ツールです。



まず、Mac 上でターミナルを開きます。

開いたら次のコマンドを実行します。

上から順に

「Ruby のアップデート」

「Cocoa Podsのインストール」

「Cocoa Podsの初期化」です。

$ sudo gem update --system
$ sudo gem install cocoapods
$ pod setup



これだけです。




Swift Realm のインストール


Swift Realm を導入します。



まず、Xcode のプロジェクトフォルダに移動します。

例えば、デスクトップに ProjectName というプロジェクトがあるならこんな感じ。

$ cd ~/Desktop/ProjectName/



次に、空の pod ファイルを作ります。

$ pod init



Podfile というファイルが出来上がるので、これに設定を書き込みます。

$ vi Podfile



vi コマンドは k, j, h, l キーがそれぞれカーソルの上下左右移動。

i キーで入力モード。

ESC で入力モードを抜けて、「:wq」で保存して終了、です。

(正確には「:w」が保存。「:q」が終了。)

target 'ProjectName' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!

# Pods for ProjectName
pod 'Realm'
pod 'RealmSwift'



終了したら Swift Realm をインストール。

$ pod install



インストールに成功すると、プロジェクトフォルダ内に

ワークスペースファイルが出来上がります。

Xcode でプロジェクトファイルを開いている場合は、

一旦閉じてワークスペースファイル(〜.xcworkspace)を開きます。



workspace に Pods プロジェクトができて、Realm がインストールされていると思います。

Xcode のファイルツリー上でプロジェクト名をクリックします。

TARGETS でプロジェクト名をクリックします。

General タブの一番下に Linked Frameworks and Libraries があるので Realm.framework を追加。



出来上がったら、試しにビルドしてみて問題なければインストール終わり。




余談ですが、vim (vi) は軽量なコマンドラインエディタです。



コマンドラインなのでとっつきにくいですが、

正規表現での一括置換や、テキストブロックでのコピペなど

通常のエディタではできない機能がかなりたくさんあります。



vim に慣れてくると、いちいちマウスでポチポチしながら

編集するのが馬鹿馬鹿しくなってきます。



Swift Realm を使う


Swift Realm では1つのテーブルを1つのクラスで表現します。

試しに、SampleDB.swift というファイルを作ります。

import Foundation
import RealmSwift

class Sample : Object {
dynamic var id:Int = 0
dynamic var name:String = ""
dynamic var password:String = ""

override static func primaryKey() -> String? {
return "id"
}

override static func indexedProperties() -> [String] {
return ["id","name","password"]
}

}

class SampleDB {
var realm = SampleDB.getRealm()

static func getRealm() -> Realm {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let realmPath = (paths[0] as NSString).appendingPathComponent("sample.realm")
let realmURL = URL(fileURLWithPath: realmPath)

return try! Realm(fileURL: realmURL)
}
}



Sample クラスがDBテーブル構造を表しています。

このサンプルコードの場合は「id Int型」「name String型」「password String型」の3種類のカラムが存在しています。



SampleDB クラスはDBアクセスクラスです。

static に Realm オブジェクトを持ってしまうのが楽かもしれません。



getRealm() 関数の中は、本当は「return try! Realm()」だけでも構いません。

ただし、その場合は Sample クラスで定義されているテーブルにだけアクセスできます。



Realm(fileURL) 関数を使うと、fileURL で渡したファイルパスのテーブルを参照します。

今回のサンプルコードの場合は「sample.realm」というファイルのテーブルを使います。



このようにしておくと、DBアクセスクラスを複数作成して、

それぞれ異なるテーブル構造を定義することが可能です。



ここまでできてしまえば、SampleDB クラスに関数を追加して

realm オブジェクトにレコードを追加したり検索したりすればOK。



Realm へのアクセス


realm オブジェクトへのアクセスは main スレッドから行う必要があります。

例えば、レコードを追加する場合はこんな感じ。

func append( item:Sample ) {
DispatchQueue.main.async {
try! self.realm.write() {
self.realm.add(item, update: true)  // データが無ければ追加、あったら上書き
}
}
}



add 関数で update:true を指定しておくとSQL 文のUPSERT相当の動きになります。



その他、Realm の詳細については公式サイトのマニュアルにサンプルコード付きで説明されています


0 件のコメント:

コメントを投稿