LoginSignup
6
6

More than 5 years have passed since last update.

【Swift4.2】Realmで連番のプライマリキーを含むデータを登録してTableViewで表示するサンプル

Last updated at Posted at 2019-01-26

登録したいデータの一覧

SampleDataModel.swift
import RealmSwift

class SampleDataModel: Object {
    @objc dynamic var id = 0
    @objc dynamic var name = ""
    @objc dynamic var memo: String?
    @objc dynamic var category = 0

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

enum SampleDataCategory: Int {
    case life
    case work
}

連番のプライマリキーが必要な場合に適合するプロトコル

RealmPrimaryKeyIncrementerProtocol.swift
import RealmSwift

protocol RealmPrimaryKeyIncrementerProtocol {
    func newId<T: Object>(model: T) -> Int
}

extension RealmPrimaryKeyIncrementerProtocol {

    func newId<T: Object>(model: T) -> Int {
        guard let key = T.primaryKey() else { fatalError("このオブジェクトにはプライマリキーがありません") }

        // Realmのインスタンスを取得
        let realm = try! Realm()
        // 最後のプライマリーキーを取得
        if let last = realm.objects(T.self).sorted(byKeyPath: "id", ascending: true).last,
            let lastId = last[key] as? Int {
            return lastId + 1 // 最後のプライマリキーに+1した数値を返す
        } else {
            return 0  // 初めて使う際は0を返す
        }
    }
}

データ登録画面(後述のTableVCからModalで遷移する)

RecordVC.swift
import UIKit
import RealmSwift

class RecordVC: UIViewController, RealmPrimaryKeyIncrementerProtocol {

    // MARK: - Properties
    @IBOutlet weak var categorySegment: UISegmentedControl!
    @IBOutlet weak var nameField: UITextField!
    @IBOutlet weak var memoField: UITextField!
    @IBOutlet weak var recordButton: UIButton!

    // MARK: - Actions
    @IBAction func recordSampleData(_ sender: UIButton) {

        let realm = try! Realm()

        let sampleData = createSampleData()

        try! realm.write {
            realm.add(sampleData)
        }
        print("Recorded:", sampleData)

        dismiss(animated: true, completion: nil)
    }

    @IBAction func cancelAndReturn(_ sender: UIBarButtonItem) {
        dismiss(animated: true, completion: nil)
    }

    // MARK: - Life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        recordButton.isEnabled = false
    }

    // MARK: - Private methods
    private func validateSampleInput() -> Bool {

        guard let nameText = nameField.text else { return false }
        let isValid = nameText.count > 2

        return isValid
    }

    private func createSampleData() -> SampleDataModel {
        let sampleData = SampleDataModel()

        sampleData.id = newId(model: sampleData)
        sampleData.name = nameField.text
        sampleData.memo = memoField.text
        sampleData.category = categorySegment.selectedSegmentIndex

        return sampleData
    }
}

// MARK: - UITextFieldDelegate
extension RecordVC: UITextFieldDelegate {
    func textFieldDidEndEditing(_ textField: UITextField) {
        recordButton.isEnabled = validateSampleInput()
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.endEditing(true)
        return true
    }

    func textFieldShouldClear(_ textField: UITextField) -> Bool {
        if textField == nameField {
            recordButton.isEnabled = false
        }
        return true
    }
}

登録したデータをTableViewで表示する

DisplayTableVC.swift
import UIKit
import RealmSwift

class DisplayTableVC: UITableViewController {

    var result: Results<SampleDataModel>?

    override func viewDidLoad() {
        super.viewDidLoad()

        let realm = try! Realm()

        result = realm.objects(SampleDataModel.self)

    }

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

        tableView.reloadData()
    }

    // MARK: - Table view data source

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

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return result?.count ?? 0
    }

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

        guard let sampleDate = result?[indexPath.row] else { return cell }

        cell.textLabel?.text = sampleDate.name
        cell.detailTextLabel?.text = sampleDate.memo

        // カテゴリーによって背景色を変える
        switch SampleDataCategory(rawValue: sampleDate.category)! {
        case .life:
            cell.backgroundColor = #colorLiteral(red: 1, green: 0.5781051517, blue: 0, alpha: 1)
        case .work:
            cell.backgroundColor = #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)
        }

        return cell
    }

全データはGitHubに上げてあります。
https://github.com/Riscait/RealmSwiftSample

6
6
2

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