post Image
Swiftで日記アプリを作ろう 〜その3 Realm活用編〜

前回の記事はこちら

いよいよRealm活用編!
値を保存する方法をマスターしましょう!

Realmの導入がまだの方はこちらから。

1. モデルファイルを作成

Realmデータベースを使うために、まずはモデルを作成しましょう。
新規ファイルを追加するときにいつも行っている「New File…」を選択します。
image

Realm Pluginが正しく導入されていれば、下にスクロールすると「Realm Model Object」が表示されています。選択して次へ。
image

Model Object Classには、「Diary」と入力。
image

最後に、「Create」ボタンをクリックして完了です。
image

2. モデルファイルの中身を考える

いま、Objectクラスを継承した「Diary」クラスを作成しました。今度はこの中身を考えていきましょう。

いま、データベースの枠を作っているものと思ってください。
日記アプリにはどの要素が必要でしょうか?

今回は、以下のようなデータベースを作成することを目標にしていきます。
image

※どうでもいいですが、筆者の実話です。

そこで、今回は一番上の部分を考えていきます。
もし要素がほかにもあるようなら、自分で追加してかんがえてみてください。

このデータベースの中身ではなく枠の部分(今回は青い背景の部分)を「エンティティ」といいます。
データベース設計を考えるときにはエンティティの設計がとても大事です。

今回は「日付」「本文」「写真」と3つのエンティティがありますが、それぞれのエンティティに名前と型をつけていきましょう。

image

それでは、上図のとおりにDiary.swiftにモデルを定義していきます。
上図のような表はデータベースを設計するときはかならず作りましょう!
Google Spreadsheetや、Excelのような表で構いません。あとで自分がコードを見たときに思い出しやすくなります。

Diary.swift
//
//  Diary.swift
//  DiarySampler
//
//  Created by Ryo Eguchi on 2017/01/02.
//  Copyright © 2017年 Ryo Eguchi. All rights reserved.
//

import Foundation
import RealmSwift

class Diary: Object {
    dynamic var date = ""
    dynamic var context = ""
    dynamic var photo: NSData? = nil

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

}

dateをPrimary Keyとして設定しました。Primary Key(以下、「PK」)として設定することで、一意性を保ちます。(重複してはいけないという意。)
※画像はその4で扱います。

それぞれのエンティティの作成方法は、チートシートを参考にしてください。

3. 日記作成画面の設置

Storyboardで、日記作成画面を作りましょう。
image

関連付けもわすれずにしておきましょう。

ViewController.swift
    @IBOutlet var writeButton: UIButton!

// (中略)

    @IBAction func writeButtonPushed(_ sender: UIButton) {


    }

続いて、2番目のViewController(DiaryViewController)についても同様に関連付けします。
あらかじめNew File…で新しくViewControllerファイルを作っておきましょう。

DiaryViewController.swift
//
//  DiaryViewController.swift
//  DiarySampler
//
//  Created by Ryo Eguchi on 2017/01/02.
//  Copyright © 2017年 Ryo Eguchi. All rights reserved.
//

import UIKit

//このファイル内でRealmを使うのでここを追加
import RealmSwift

class DiaryViewController: UIViewController {

    @IBOutlet var dateLabel: UILabel!

    @IBOutlet var contextTextView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

    }

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

    @IBAction func saveButtonPushed(_ sender: UIButton) {
    }

}

4. 情報をDiaryViewControllerに集約させよう

今回のアプリの構造は次のとおりです。
image

つまり、すべての情報が「DiaryViewController」に集約され、そこから情報がRealm Databaseに格納されます。
そこで、情報をすべてDiaryViewControllerに集約させましょう。

4-1. dateの受け皿を準備する

DiaryViewControllerに、dateの受け皿を準備しましょう。
変数を宣言します。

DiaryViewController.swift
    var date: String!

実際にラベルに表示させるようにしておきましょう。

DiaryViewController.swift
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        dateLabel.text = date

    }

4-2. 受け渡し元のViewControllerで処理を記述

ViewController.swift
    var date: String!

    // (中略)

    func didSelectDay(_ dayView: JBDatePickerDayView) {
        print("date selected: \(dateFormatter.string(from: dayView.date!))")
        date = dateFormatter.string(from: dayView.date!) //追加

    }

    @IBAction func writeButtonPushed(_ sender: UIButton) {
        self.performSegue(withIdentifier: "toDiary", sender: nil)
    }


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if (segue.identifier == "toDiary") {
            let diaryView = segue.destination as! DiaryViewController
            diaryView.date = self.date
        }
    }

まずはじめに、dateをString型で宣言しておきます。

1つめのメソッド「didSelectDay」は、JBDatePickerDayViewのDelegateメソッドです。
dateにstring型で日付を挿入しています。

2つめのメソッド「writeButtonPushed」は、「書く」ボタンをおした時のメソッドで、画面遷移のコードを書いています。

3つめのメソッド「prepare for segue」は、画面遷移するときに必ず呼ばれるメソッドです。(知らなかったら覚えておこう!)
今回は、「toDiary」の画面遷移をするときに、遷移先のdateという変数に遷移元の変数dateの値を代入します。これで、画面遷移したときに遷移先のdate変数に初期値がセットされました。

4-3. Storyboardで画面をつなげる

Storyboardで1つめの画面と2つめの画面をつなげておきましょう。
Identifierは「toDiary」と記述します。
image

これで、保存はされませんが、シミュレータで実行して画面遷移ができることを確認しましょう。

image

ただしく実行できれば、上図のように画面上部のラベルに日付が表示されます。

5. Realmに保存

最後に、Realmに保存(書き込み)しましょう。

DiaryViewController.swift
    @IBAction func saveButtonPushed(_ sender: UIButton) {

        // STEP.1 Realmを初期化
        let realm = try! Realm()

        //STEP.2 保存する要素を書く
        let diary = Diary()
        diary.date = date
        diary.context = contextTextView.text

        //STEP.3 Realmに書き込み
        try! realm.write {
            realm.add(diary, update: true)
        }


        //画面遷移して前の画面に戻る
        self.dismiss(animated: true, completion: nil)

    }

この地点でRealmに値を書き込んでいるので、きちんと値が書き込まれているかRealm Browserで確認してみましょう。
確認方法はこちらの記事が参考になります。
【Swift】Realm BrowserでRealm Mobile Databaseの中身を確認する

6. Realmから値を読み込む

もし、すでにRealmに値がある場合は、Realmから本文を取ってくるようにしましょう。

DiaryViewController.swift
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        dateLabel.text = date

        DispatchQueue(label: "background").async {
            let realm = try! Realm()

            if let savedDiary = realm.objects(Diary.self).filter("date == '\(self.date!)'").last {
                let context = savedDiary.context
                DispatchQueue.main.async {
                    self.contextTextView.text = context
                }
            }
        }

    }

DispatchQueue(label:"background")では、メインスレッドではなくバックスレッドで処理を実行しています。これをすることで、メインスレッドの処理に影響することなくバックスレッドでQueue(検索して読み込み)を行うことができます。

let savedDiary = realm.objects(Diary.self).filter("date == '\(self.date!)'").last

これは、

realm.objects(Diary.self)

ここで、Diaryオブジェクトをすべて読みこんでいます。そこに、

.filter("date == '\(self.date!)'")

filter(フィルタ)をかけてあげます。今回は、dateエンティティが「self.date!」(選択した日付)と等しいものをすべて読み込んでいます。

さらに、

.last

これで、フィルタをかけたオブジェクトのうちで一番最後(最新)のもの、という意味です。

DispatchQueue.main.async {
   self.contextTextView.text = context
}

これは、DispatchQueueで処理するスレッドを変えていますが、画面表示に関わることなのでバックスレッドでは処理できません。そこで、あえてメインスレッドに変えて処理を実行しています。


『 Swift 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。