无法使用 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
包含不存在的索引。
目标
我正在尝试更新一些记录,然后从 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
包含不存在的索引。