LoginSignup
5
6

More than 3 years have passed since last update.

[Swift] Realmを実装して分かったこと色々

Last updated at Posted at 2021-01-17

はじめに

Realmを以下の記事を参考に実装しました。
https://qiita.com/pe-ta/items/616e0dbd364179ca284b
以下のリンクから動き確認できます。
https://twitter.com/vex3ex5frd2xcvg/status/1350637210106699777?s=21
そこから色々調べてみたので、自分なりに理解した事を書いてみようと思います。
実装の手順などは、以下の記事から確認してください。

実装

① importする

まずはRealmSwiftをimportします。
RealmSwiftが必要な箇所でそれぞれimportしてみてください。
はじめはエラーになりますので、1度ビルドする事でimport出来ます。

ViewController.swift
import UIKit
// RealmSwiftをimportするとエラーになるが、ビルドしたら治る
import RealmSwift

② モデルクラスの作成

ファイルの追加でswiftファイルを作成してください。
このファイルでは、Realmで扱うデータの項目とその型を定義します。
要は、このプロパティに値を保存していくイメージになります。
Realmモデルのプロパティには@objcdynamicをつける必要があります。

TodoModel.swift
import Foundation
import RealmSwift

class TodoModel: Object {
    @objc dynamic var koumoku: String? = nil
}

③ viewControllerに変数を用意

Resultsは「オブジェクトから返される Realm の自動更新コンテナ型」だそうです。
この変数にデータを追加していくことになります。

ViewController.swift
    // 作成したTodoModel型の変数を用意。
    // Realmから受け取るデータを入れる変数
    var itemList: Results<TodoModel>!

④ viewDidLoadでインスタンス化

今回使用するRealmをインスタンス化して使えるようにします。
次に、object()を使用します。これは()内に指定したデータを全て取得できるものなので、
取得を行い、取得したデータを③で作成した変数に入れます。

ViewController.swift
override func viewDidLoad() {
        super.viewDidLoad()

        // Realmをインスタンス化する
        let realm = try! Realm()

        // objects()はRealmに保存されている指定されたデータを全て取得する!
        // object().filter()でさらにフィルタリングして指定することもできるそうです。
        self.itemList = realm.objects(TodoModel.self)
    }

⑤ データを追加して保存していく

今回はbuttonを押したらtextFieldに書いた内容が追加されるようにします。
追加・保存を行いたいAction内で書いてみてください。

1.追加していく場所は、②で作成したモデルクラス内のプロパティになりますので、モデルクラスをインスタンス化していきます。
2.textField.textを②で作成したkoumokuプロパティに入れます。
3.buttonAction内でもRealmを使うので、viewDidLoad内で作成したように、Realmをインスタンス化します。
4.realm.writeはRealmインスタンスを最新版に更新し、該当する場合は通知を作成すると公式ドキュメントにありました。
2でデータを更新しているので、realm.writeで最新のものを取得しているわけです。
realm.add()は管理されていないオブジェクトを()内のRealmに追加します。
つまり、realm.add()で管理されてない(追加したデータ)をRealmに追加して、
realm.writeでその最新バージョンを取得しているわけです。

ViewController.swift
    @IBAction func addButton(_ sender: Any) {
        // 1.モデルクラスをインスタンス化。これでアクセスできるようになる!
        let instanceTodoModel: TodoModel = TodoModel()
        // 2.textFieldの値をぶち込む
        instanceTodoModel.koumoku = self.textField.text

        // 3.Realmをインスタンス化してデータベースを取得!viewDidLoadでも行ったやつ
        let realm = try! Realm()

        // 4.textFieldの値をデータベースに追加する
        // write は refresh() が呼び出されたかのように Realm インスタンスを最新の Realm バージョンに更新し、該当する場合は通知を生成します。
        try! realm.write {
            realm.add(instanceTodoModel)
        }
        self.tableView.reloadData()
    }

⑥ TableViewの実装

itemListにRealmから受け取ったデータが入っているので、それを使用してTableViewCellを作成していきます。

ViewController.swift
extension ViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.itemList.count
    }

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

        let item: TodoModel = self.itemList[indexPath.row]

        cell.textLabel?.text = item.koumoku

        return cell
    }

⑦ 削除機能

Viewcontroller.swift
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        // この中でもRealmを使えるようにインスタンス化
        let realm = try! Realm()

        if editingStyle == .delete {
            // 削除したいデータを検索する。今回はdeleteしたいcellのindexpath.row番目の項目を削除したいので、それをobjectで指定。
            let deleteItem = realm.objects(TodoModel.self)[indexPath.row]

            do{
                // write は refresh() が呼び出されたかのように Realm インスタンスを最新の Realm バージョンに更新し、該当する場合は通知を生成します。
                try realm.write{
                    // 追加の時のaddの削除版
                    realm.delete(deleteItem)
                }
            }catch{
                    print("Error")
                }
            }
        tableView.reloadData()

        }

実際のコード

ViewController.swift
import UIKit
// RealmSwiftをimportするとエラーになるが、ビルドしたら治る
import RealmSwift

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var tableView: UITableView!

    // 作成したTodoModel型の変数を用意。
    // Realmから受け取るデータを入れる変数
    var itemList: Results<TodoModel>!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Realmをインスタンス化する
        let realm = try! Realm()

        // objects()はRealmに保存されている指定されたデータを全て取得する!
        self.itemList = realm.objects(TodoModel.self)
    }

    @IBAction func addButton(_ sender: Any) {
        // モデルクラスをインスタンス化。これでアクセスできるようになる!
        let instanceTodoModel: TodoModel = TodoModel()
        // textFieldの値をぶち込む
        instanceTodoModel.koumoku = self.textField.text

        // Realmをインスタンス化してデータベースを取得!viewDidLoadでも行ったやつ
        let realm = try! Realm()

        //Realmインスタンスからaddを叩くと、データベースにレコードが追加される
        // textFieldの値をデータベースに追加する
        // write は refresh() が呼び出されたかのように Realm インスタンスを最新の Realm バージョンに更新し、該当する場合は通知を生成します。
        try! realm.write {
            realm.add(instanceTodoModel)
        }
        self.tableView.reloadData()
    }
}

extension ViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.itemList.count
    }

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

        let item: TodoModel = self.itemList[indexPath.row]

        cell.textLabel?.text = item.koumoku

        return cell
    }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        let realm = try! Realm()

        if editingStyle == .delete {
            // 削除したいデータを検索する。今回はdeleteしたいcellのindexpathの項目を削除したいので、それをobjectで指定。
            let deleteItem = realm.objects(TodoModel.self)[indexPath.row]

            do{
                // write は refresh() が呼び出されたかのように Realm インスタンスを最新の Realm バージョンに更新し、該当する場合は通知を生成します。
                try realm.write{
                    realm.delete(deleteItem)
                }
            }catch{
                    print("Error")
                }
            }
        tableView.reloadData()

        }
}
TodoModel.swift
import Foundation
import RealmSwift

class TodoModel: Object {
    @objc dynamic var koumoku: String? = nil
}

起動してみた

ツイートしてあるので、リンク貼っておきます。
https://twitter.com/vex3ex5frd2xcvg/status/1350637210106699777?s=21

参考サイト

https://qiita.com/pe-ta/items/616e0dbd364179ca284b
https://naoya-ono.com/swift/realm-update-delete/

5
6
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
5
6