Realm

Swift:超簡単データベース!Realmを使った超簡単お手軽Todoアプリ!!


今回は、

ホットなデータベースサービス『Realm』を使ってみようかと思います。

超簡単Todoアプリでお試しします!!
(Todoアプリと呼んでいいのか怪しいレベルです。。。)

*この記事は超初心者に向けたものなので、Realmの登場はかなり下の方になります。あしからず。

 

Realmとは

iosアプリのデータベースといえば
『CoreData』というものあり、
なんでもできて便利らしいのですが、

めっちゃ難しいらしいです。

そこで、
『Realm』が人気を博しているようです。
とにかく簡単に書けるので、
初心者に向いてるらしいです。

詳しくは、こちらの素晴らしい記事をご覧ください。

qiita.com

 

プロジェクト名は『RealmApp』にしました。

 

まずはStoryBoardを開いてください。

デフォルトのViewControllerがありますよね、

それは削除して、

新しくUITableViewControllerを配置してください。

それにUINavigationControllerを紐付けましょう。

f:id:jumprails3303:20161128011520p:plain

1. TableViewControllerを選択した状態で、

2. EditorのEmbed in

3. 『Navigation Controller』を選択。

 

それができると、このような状態になります。
f:id:jumprails3303:20161128011553p:plain

 

デフォルトのViewControllerを消したせいで、
最初に表示されるViewがわからなくなってしまっているので、指定してあげましょう。

①UINavigationControllerを選択して

②attributes inspectorボタンをクリック

③『is initial View Controller』にチェック!!

f:id:jumprails3303:20161128012154p:plain

新しくUITableViewControllerを配置したので、
それに対応したファイルも作成しましょう。

File → New → File で

f:id:jumprails3303:20161128012618p:plain

 

CocoaTouchClassを選択してください。
f:id:jumprails3303:20161128012648p:plain

 

そして、Nameはシンプルに『TableViewController』にしましょう!
f:id:jumprails3303:20161128013418p:plain

 

今作成したファイルを早速、StoryBoard上のUITableViewControllerに適応させましょう!
①UITableViewControllerを選択して、
②新聞紙マークをクリックし、
③classに『TableViewController』と入力しましょう。
f:id:jumprails3303:20161128013407p:plain

次に
①新しいUIViewController(Todoを追加するページ)を配置します。
②TableViewControllerからViewControllerへ『show』でセグエを設定。
f:id:jumprails3303:20161128015335p:plain

③segueのidentifierを『goCreate』を設定。
f:id:jumprails3303:20161128015843p:plain

 

ここでコードをいじります。

UINavigationBarをカスタム

最初にくっつけたNavigationControllerを使っていきます。

TableViewController.swiftを編集します。

* コメントアウトされたいらない部分の削除

* コメントアウトされた必要な部分のコメントアウトを外す。

* navigationBarのカスタム

* セグエについて
これらを意識して、編集しました。

import UIKit

class TableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "作成", style: .plain, target: self, action: #selector(self.goCreate))
        
    }
    
    
    
    
    func goCreate() {
        performSegue(withIdentifier: "goCreate", sender: nil)
    }

    @IBAction func unwindToTop(segue: UIStoryboardSegue) {
    }
    
    
    
    

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 0
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return 0
    }

    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)

        // Configure the cell...

        return cell
    } 

}

UINavigationBarのカスタマイズについて

こちらをご覧ください。

 

UINavigationControllerのセグエについて

こちらをご覧ください。

 

ひとまずコードは置いておいて、

StoryBoardに戻りましょう。

先ほど配置した新しいUIViewControllerにUIButtonを配置しましょう。場所は適当でいいですよ
f:id:jumprails3303:20161128020846p:plain

 

そして、
配置したUIButtonから、
UIViewControllerの上部にある3つのボタンの中の一番右まで「control + drag」です。
『unWindToTopSegue…』という表示が出てくるので、選択してください。
f:id:jumprails3303:20161128021600p:plain

 

ここまで、一応動くところまできました。Runしてみましょう。

 

 

そしてStoryBoardにて、
UIViewController上に

* 『UILabel』・・・todoにテキストを変更。

* 『UITextField』・・・配置しただけ。

をこのように配置してください。
UIButtonも『リストに追加』に変更しましょう。
f:id:jumprails3303:20161128212152p:plain

そういえばまだ、UIViewControllerに対応してファイルを作成していませんでした。
『CreateViewController』で作成してください。
TableViewControllerに対応するファイルを作った時と同じ手順です。
Todoを作る(create)ページにする予定なのでこの名前にしました。

次に配置したUITextFieldとコードを結びつけましょう。
名前は普通に『textField』にしましょう。
f:id:jumprails3303:20161128213206p:plain

UIButtonも同じようにコードと結びつけましょう。
名前は『createButton』にしましょう。
f:id:jumprails3303:20161128213316p:plain

 

Realmの登場!!

お待たせしました!
そろそろRealm登場させます。

podfileを開いて

pod ‘RealmSwift’

という項目を追加しましょう。

そしてターミナルにて

$ pod install

してください。

これでRealmが使えるようになりました。

Xcodeworkspaceを開いてください。

 

Todoを司るTodo.swift

次にTodo.swiftというtodoの内容を記述するファイルを作成します。
内容と言っても今回はTodoのタイトルしか記述するつもりはないのです。
いつもどうりCocoa Touch Classを選択してください。

ここからが少し違って、
subclassを『NSObject』してください。
名前はもちろん『Todo』!!!
f:id:jumprails3303:20161128214610p:plain

このようになっていると思います。

import UIKit

class Todo: NSObject {

}

それをこのように編集しましょう。
import UIKit
import RealmSwift



class Todo: Object {
    @objc dynamic var title = ""
    
}

 

import RealmSwift

このimportによってRealmSwiftを使えるようにしました。
ライブラリを使う際はほとんどこのimportを使います。

dynamic

Realmを使用する際、プロパティにはdynamicをつけるルールです。

 

そろそろ終わりが近づいてきました。

CreateViewController.swiftをこのように編集しましょう!!

import UIKit
import RealmSwift


class CreateViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
        
        
        textField.delegate = self
    }

    
    
    
    
    
    
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    
    @IBAction func createButton(_ sender: Any) {
        let realm = try! Realm()
        
        let todo = Todo()
        todo.title = textField.text!
        try! realm.write {
            realm.add(todo)
        }
        self.dismiss(animated: true, completion: nil)
    }
    
    
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        self.textField.resignFirstResponder()
        return true
    }

    
  

}

try! Realm()

このtry! Realm()はデータを扱う際に使います。使う頻度はかなり高いです。
Realmデータベースをインスタンス化しているとか、参照しているとか、
そんな感じです。

ここでは保存する際に使用してます。

try! realm.write {
            realm.add(todo)
        }

『write』内で書くことでデータを永続化できます。
データを加えているのが『add』ですね。

それらをcreateButtonの中に書くことによって
ボタンをタップした際に処理が行われます。

しれっと書いたtextFieldDelegateについては
こちらの記事をご覧ください。今回は省きます。

こちら!

 

次にTableViewControllerをこのように編集しましょう。

import UIKit
import RealmSwift

class TableViewController: UITableViewController {
    
    
    let realm = try! Realm() //いつもの
 
    override func viewDidLoad() {
        super.viewDidLoad()

        
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "作成", style: .plain, target: self, action: #selector(self.goCreate))
        
    }
    
    
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated: true)
        tableView.reloadData()
    }
    
    func goCreate() {
        performSegue(withIdentifier: "goCreate", sender: nil)
    }

    @IBAction func unwindToTop(segue: UIStoryboardSegue) {
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }


    override func numberOfSections(in tableView: UITableView) -> Int {

        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        let todoCollection = realm.objects(Todo.self)
        // Realmに保存されているTodo型のobjectsを取得。
        
        return todoCollection.count // 総todo数を返している
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
        let todoCollection = realm.objects(Todo.self)
        // Realmに保存されているTodo型のobjectsを取得。
        let todo = todoCollection[indexPath.row]
        cell.textLabel?.text = todo.title

        return cell
    }
    
    

    

}

説明が必要なところはviewWillAppearとtableView系の関数についてですね。

viewWillAppear

この関数はviewが表示される前に行いたい処理を書きます。

今回は、CreateViewControllerでTodoを作成して、TableViewControllerに戻った時に、TableViewの内容をリロードする必要があるので、

tableView.reloadData()

を記述します。

 

tableView系

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        let todoCollection = realm.objects(Todo.self)
        // Realmに保存されているTodo型のobjectsを取得。
        
        return todoCollection.count // 総todo数を返している

}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)

        let todoCollection = realm.objects(Todo.self)
        // Realmに保存されているTodo型のobjectsを取得。

        let todo = todoCollection[indexPath.row]
        cell.textLabel?.text = todo.title

        return cell
}

ここかと思います。
コメントアウトに記述しているとおり
『objects()』によって保存されているデータを取得できます。

TableViewControllerについての詳しい使い方は
こちらをご覧ください。

 

最後に忘れていた。
cellのIdentifierを書きましょう。

 tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)

ここにデフォルトで記述されている『reuseIdentifier』をIdentifierに登録してください。
f:id:jumprails3303:20161128225846p:plain

 

これで完成です!!


ABOUT ME
ささお
3年目iOSエンジニア。 スタートアップで働いておりやす。 プログラミングスクールとエンジニアのキャリアを考えたい。 作ったアプリ - https://apps.apple.com/us/app/loverprofile/id1463563845?l=ja&ls=1