今回はiOSアプリでリレーショナル・データベースを利用する際によく使われるRealm
、RealmSwift
を使ってTODOアプリを作成していきます。
講義の目標
Realmを使ってデータベースを利用できるようになること
Xcoeeプロジェクトの作成 新規プロジェクトを立ち上げます。その際、使用するテンプレートはSingle View Application
となります。
入力項目
入力値
Product Name
Todo
Team
None
Oganization Name
任意(”ALJ”など自分が所属している組織の名前を入れる)
Oganization Identifier
jp.co.al-j
Language
Swift
Devices
iPhone
Use Core Data
チェックを外す
include Unit Tests
チェックを外す
include UI Tests
チェックを外す
Realmとは リレーショナル・データベースの一種で、iOSだけでなく、Android版にもある新しいデータベースエンジンです。
Realmの特徴 Realmは下記のような特徴を持っています。
処理速度が早い
データベース処理の構文がシンプル
テーブル定義もSwiftのクラスファイルで記述
RealmSwiftとは RealmSwiftはそのRealmをSwiftで使うためのライブラリです。Realm
、RealmSwift
を利用する事により高速にデータベースを利用したアプリを作成する事が可能です。
Realm、RealmSwiftの導入方法 Realm
、RealmSwift
の導入にはCocoaPods
を使っていきます。 ターミナルでプロジェクトフォルダに移動し、下記のコマンドを実行します。
ターミナル操作
Podfile
が作成されますのでそれをテキストエディタで開き、下記の内容へ修正し、保存してください。
ターミナル操作
Podfile
platform :ios, '8.0' use_frameworks! target 'Todo' do pod 'Realm', :git => 'https://github.com/realm/realm-cocoa.git', :branch => 'swift-2.0' pod 'RealmSwift', :git => 'https://github.com/realm/realm-cocoa.git', :branch => 'swift-2.0' end
そしてpod install
をしてRealm
、RealmSwift
の導入します。
下記のようなメッセージがターミナルで表示されればインストール完了です。
Installing Realm (0.98.2) Installing RealmSwift (0.98.2) Generating Pods project Integrating client project [!] Please close any current Xcode sessions and use `Todo.xcworkspace` for this project from now on. Sending stats Pod installation complete! There are 2 dependencies from the Podfile and 2 total pods installed.
一度開いているXcodeプロジェクトを閉じて、Todo.xcworkspace
をXcodeで開くことによりRealm
、RealmSwift
を利用して開発できるようになります。
モデルの定義 まずRealmのようなリレーショナル・データベースを利用するためには、モデルを作成しないといけません。モデルとは データベースをどのように構成するかということを定義したものです。
今回はTODOアプリですので、下記のようなモデルを作成する必要があります。
項目名
説明
name
TODO項目の名前
desc
TODO項目の説明文
isComplete
TODO完了有無(trueが完了、falseが未完了)
Xcodeプロジェクトにてプロジェクト内に新しいSwiftクラスを作成します。 下図のとおりNew File
でファイルを作成してください。 ファイル名はToDo.swift
にします。
ToDo.swift
ファイルに上記のモデルを定義していきます。
ToDo.swift
import Foundationimport RealmSwiftclass ToDo : Object { dynamic var name = "" dynamic var desc = "" dynamic var isComplete = false dynamic var createDate = NSDate (timeIntervalSince1970: 0 ) dynamic var updateDate = NSDate (timeIntervalSince1970: 0 ) }
画面レイアウト構築 TODO一覧画面 Main.storyboard
で画面レイアウトを構築していきます。 初期表示のViewControllerは4インチサイズにしておきましょう。
次にNavigationController
を追加してTODOリストとTODO詳細を行き来できるようにします。 メニューバーからEditer -> Embed in -> NavigationController
を選択してください。
このようにNavigationController
が追加されます。
ViewControllerにTableView
を配置します。下図のとおりPrototype Cell
を1
にしてください。
TableViewCell
を選択して、Identifier
をCell
にします。
ナビゲーションバーのタイトルをTODO一覧
にし、Bar Button Item
を追加してSystem Item
をadd
にします。
TODO登録・編集画面 次にTODO登録・編集する画面を追加します。Main.storyboard
でViewControllerを追加します。 画面サイズも4インチにしておいてください。
まずSegue
をつなげておきましょう。Segue
のIdentifier
はtoDetail
にします。
下図のとおりに、TextField
、Label
、TextView
、Button
、Bar Button Item
を追加してください。
配置できたらTodoDetailViewController.swift
ファイルを作成し、追加した画面と関連付けます。
次に下図のとおりIBOutlet接続してください。
@IBOutlet weak var titleField: UITextField !@IBOutlet weak var descTextView: UITextView !@IBOutlet weak var commitButton: UIButton !@IBOutlet weak var trashButton: UIBarButtonItem !
TODO登録機能 それではTODO登録機能を追加します。
TodoDetailViewController.swift
import UIKitimport RealmSwiftclass TodoDetailViewController : UIViewController { @IBOutlet weak var titleField: UITextField ! @IBOutlet weak var descTextView: UITextView ! @IBOutlet weak var commitButton: UIButton ! @IBOutlet weak var trashButton: UIBarButtonItem ! var actionType = "" var selectedTodo:ToDo ! override func viewDidLoad () { super .viewDidLoad() self .initView() } func initView () { if actionType == "NEW" { self .title = "TODO新規追加" self .commitButton.setTitle("新規追加" , forState: .Normal ) self .commitButton.addTarget(self , action: "dbAdd:" , forControlEvents: .TouchUpInside ) self .titleField.text = "" self .descTextView.text = "" self .navigationItem.rightBarButtonItem = nil } else if actionType == "UPDATE" { self .title = "TODO編集" self .commitButton.setTitle("更新" , forState: .Normal ) self .commitButton.addTarget(self , action: "dbUpdate:" , forControlEvents: .TouchUpInside ) self .titleField.text = selectedTodo.name self .descTextView.text = selectedTodo.desc } } @IBAction func dbAdd (sender: AnyObject) { if isValidateInputContents() == false { return } let toDo = ToDo () toDo.name = titleField.text! toDo.createDate = NSDate () do { let realm = try Realm () try realm.write{ realm.add(toDo) } print ("DB登録成功" ) }catch { print ("DB登録失敗" ) } self .navigationController?.popViewControllerAnimated(true ) } private func isValidateInputContents () -> Bool { if let title = titleField.text{ if title.characters.count == 0 { return false } }else { return false } return true } }
TODO一覧画面から画面遷移できるようにコードを追加します。 TODO登録時にrealm
インスタンスを生成してwrite
メソッドでTODOデータを保存する処理を実行しています。 また今回はTODO登録・編集画面は、新規登録時、編集時で共有して使いますので、新規作成アクション時にはactionType
をNEW
にセットして画面遷移します。
ViewController.swift
class ViewController : UIViewController { var actionType = "" var selectedTodo:ToDo ! override func viewDidLoad () { super .viewDidLoad() } override func didReceiveMemoryWarning () { super .didReceiveMemoryWarning() } @IBAction func addButtonTapped (sender: AnyObject) { self .actionType = "NEW" self .performSegueWithIdentifier("toDetail" , sender: nil ) } override func prepareForSegue (segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "toDetail" { let vc = segue.destinationViewController as ! TodoDetailViewController vc.actionType = self .actionType } } }
IBAction
メソッドを追加したので、Main.storyboardで関連付けしておきましょう。
それではこの状態で一度Runして確認してみましょう。デバッグエリアに失敗
というメッセージが出ていなければRealmにデータが保存されています。
Realm Browserでデータを確認 今保存したRealmのデータをRealm Browser
というツールを使って確認してみましょう。 下記URLをクリックしてRealm Browser
をインストールしましょう。
https://itunes.apple.com/jp/app/realm-browser/id1007457278?mt=12
Realmデータ確認方法 Realm Browser
をインストール完了して、Realmを使ったiOSアプリをシュミレータで動作させた場合には、下記のコマンドをターミナルで実行すれば、Realm Browser
で中身を開く事ができます。
ターミナルで実行
open $(find ~/Library/Developer/CoreSimulator/Devices/$(ls -t1 ~/Library/Developer/CoreSimulator/Devices/ | head -1)/data/Containers/Data/Application/ -name \*.realm)
下記のような画面が出ますのでAllow
をクリックしてください。
このようにRealm Browsetでデータの中身を確認できます。
TODO一覧表示機能 それではRealmに保存されたデータをTODO一覧画面に表示させましょう。 ViewController.swiftにコードを追加してください。
ViewController.swift
import UIKitimport RealmSwiftclass ViewController : UIViewController ,UITableViewDataSource ,UITableViewDelegate { @IBOutlet weak var tableView: UITableView ! var todoItems:Results <ToDo >?{ do { let realm = try Realm () return realm.objects(ToDo ).sorted("createDate" ) }catch { print ("エラー" ) } return nil } var actionType = "" var selectedTodo:ToDo ! override func viewDidLoad () { super .viewDidLoad() tableView.delegate = self tableView.dataSource = self } override func viewWillAppear (animated: Bool) { super .viewWillAppear(animated) tableView.reloadData() } : : func numberOfSectionsInTableView (tableView: UITableView) -> Int { return 1 } func tableView (tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return todoItems!.count } func tableView (tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("Cell" , forIndexPath: indexPath) let toDo = todoItems?[indexPath.row] cell.textLabel?.text = toDo?.name return cell }
メンバ変数にvar todoItems:Results<ToDo>
を定義する事により、ToDo
のデータオブジェクト形式のRealmデータを常に保持するようになります。こうする事によりRealmのToDoデータが更新される度にこのtodoItems
の中もデータが更新されるようになります。 そのtodoItems
の配列をもとにTableViewDataSource
にてテーブルビューの表示仕様を確定させ、画面にTODOデータを表示させています。
IBOutlet
を追加しましたので、Main.storyboardを開いて関連付けしてください。
それではRunして動作確認してみましょう。TODO一覧画面にて登録したTODOアイテムが表示されていればOKです。
TODO編集機能 次にTableViewCellをタップしたらTODO編集・登録画面へ遷移し、登録しているTODOを編集できるようにします。ViewController.swiftにてセルタップ時の処理を追加し、actionType
をUPDATE
にし、選択されたセルのTodoデータを画面遷移時に送信するようにします。
ViewController.swift
override func prepareForSegue (segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "toDetail" { let vc = segue.destinationViewController as ! TodoDetailViewController vc.actionType = self .actionType vc.selectedTodo = selectedTodo } } func tableView (tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { self .actionType = "UPDATE" selectedTodo = todoItems?[indexPath.row] self .performSegueWithIdentifier("toDetail" , sender: selectedTodo) }
次に、TodoDetailViewController
で、DBを更新する処理を追加します。
@IBAction func dbUpdate (sender: AnyObject) { do { let realm = try Realm () try realm.write{ selectedTodo.name = self .titleField.text! selectedTodo.desc = self .descTextView.text selectedTodo.updateDate = NSDate () } print ("DB更新成功" ) }catch { print ("DB更新失敗" ) } self .navigationController?.popViewControllerAnimated(true ) }
この状態でRunして確認してみましょう。登録済みのTODOが更新できる事を確認してください。
TOOD削除機能 最後にTODOを削除する機能を追加します。
TodoDetailViewController.swift
@IBAction func dbDelete (sender: AnyObject) { do { let realm = try Realm () try realm.write{ realm.delete(selectedTodo) } }catch { print ("失敗" ) } self .navigationController?.popViewControllerAnimated(true ) }
追加したIBAction
をMain.storyboardで関連付します。
これでTODOアプリは完成です。Realm
とRealmSwift
を使うことにより簡単にデータベースを利用できる事ができます。 今回作成したTodoアプリは非常にシンプルなものですが、完了期日を設定したり、タグをつける機能をつけたりして是非高機能にしていってください。