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

## 登録したいデータの一覧

```swift: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
}

```
## 連番のプライマリキーが必要な場合に適合するプロトコル
```swift: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で遷移する）
```swift: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で表示する
```swift: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