无法使用 Realm 保存多条记录

Not able to save multiple records with Realm

目标

我正在尝试更新一些记录,然后从 NSTableView 中删除它们。 http://take.ms/6r3IV

预期结果

我希望我的记录会更新,NSTableView 会重新加载以反映我的更改。

实际结果

我的应用程序崩溃了。 http://take.ms/q6SWw

重现步骤

我们可以遵循哪些步骤来重现此问题?

代码示例

https://gist.github.com/msamoylov/27e1b6c9255b254f033f44d6de115d20

领域和工具的版本

Realm version: 2.0.0 (installed as the Dynamic Framework)

Xcode version: 8.0 (8A218a)

macOS version: 10.12

看来我没有正确处理通知。所以,我最终以这种方式重写了我的代码:

import Cocoa
import RealmSwift


class ExerciseListViewController: NSViewController {
    @IBOutlet weak var exerciseTableView: NSTableView!

    let realm = try! Realm()
    var exercises = try! Realm().objects(Exercise.self).filter("preferred = false").sorted(byProperty: "priority")
    var notificationToken: NotificationToken? = nil

    override func viewDidLoad() {
        super.viewDidLoad()

        exerciseTableView.dataSource = self
        exerciseTableView.delegate = self
        exerciseTableView.doubleAction = #selector(self.addPreferredExercises(_:))

        notificationToken = exercises.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
            guard let exerciseTableView = self?.exerciseTableView else { return }
            switch changes {
            case .initial:
                exerciseTableView.reloadData()
                break
            case .update(_, let deletions, let insertions, _):
                exerciseTableView.beginUpdates()
                exerciseTableView.insertRows(at: IndexSet(insertions), withAnimation: .slideDown)
                exerciseTableView.removeRows(at: IndexSet(deletions), withAnimation: .effectFade)
                exerciseTableView.endUpdates()

                if self?.exercises.count == 0 {
                    self?.dismiss(nil)
                }

                break
            case .error(let error):
                fatalError("\(error)")
                break
            }
        }
    }


    deinit {
        notificationToken?.stop()
    }


    @IBAction func addPreferredExercises(_ sender: AnyObject) {
        if exerciseTableView.selectedRowIndexes.isEmpty {
            let alert = NSAlert()
            alert.messageText = "Hint"
            alert.informativeText = "Please select at least one exercise from the list."
            alert.alertStyle = .informational
            alert.beginSheetModal(for: view.window!, completionHandler: nil)
        }

        try! realm.write {
            for index in exerciseTableView.selectedRowIndexes {
                if exercises.indices.contains(index) {
                    let exercise = exercises[index]
                    exercise.preferred = true
                }
            }
        }
    }
}

extension ExerciseListViewController: NSTableViewDataSource, NSTableViewDelegate {
    func numberOfRows(in tableView: NSTableView) -> Int {
        return exercises.count
    }


    func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
        return exercises.indices.contains(row) ? exercises[row].name : nil
    }


    func tableView(_ tableView: NSTableView, toolTipFor cell: NSCell, rect: NSRectPointer, tableColumn: NSTableColumn?, row: Int, mouseLocation: NSPoint) -> String {
        let exercise = exercises[row]
        let comment = exercise.comment as String!

        return comment!
    }
}

它仍然不能 100% 正确地处理多项选择,但至少它不会再让应用程序崩溃了。由于某种原因 exerciseTableView.selectedRowIndexes 包含不存在的索引。