领域通知导致异常:对象已被删除或无效

时间:2018-05-23 19:10:47

标签: realm

Swift 4,Realm 3.5

我在NSOutlineView上设置了一个适用于插入和修改的领域通知,但删除始终会导致此异常:

2018-05-23 11:57:09.890455-0700 MyApp[57060:9443837] [General] Object has been deleted or invalidated.
2018-05-23 11:57:09.893594-0700 MyApp[57060:9443837] [General] (
  0   CoreFoundation                      0x00007fff27eeb32b __exceptionPreprocess + 171
  1   libobjc.A.dylib                     0x00007fff4f565c76 objc_exception_throw + 48
  2   Realm                               0x000000010074696f ___ZN12_GLOBAL__N_115makeBoxedGetterIN5realm10StringDataEEEP11objc_objectm_block_invoke + 289
  3   Foundation                          0x00007fff29f7404c -[NSObject(NSKeyValueCoding) valueForKey:] + 284
  4   Realm                               0x00000001007618b1 -[RLMObjectBase valueForKey:] + 85
  5   Realm                               0x0000000100762b77 -[RLMObjectBase hash] + 145
  6   Foundation                          0x00007fff29f4a3eb probeGC + 80
  7   Foundation                          0x00007fff29f4d994 -[NSConcreteMapTable removeObjectForKey:] + 56
  8   AppKit                              0x00007fff255d262f _NSOVFreeRowEntry + 59
  9   AppKit                              0x00007fff25abc83a __70-[NSOutlineView _removeItemsAtIndexes:inParentRowEntry:withAnimation:]_block_invoke + 253
  ...

以下是我的通知观察者的样子:

let realm = try! Realm()
let results = realm.objects(Workspace.self).sorted(byKeyPath: "order", ascending: true)

tokenWorkspace?.invalidate()
tokenWorkspace = results.observe { [weak self] (changes: RealmCollectionChange) in
  switch changes {
  case .initial:
    //The listener is ready
    self?.refreshData(reload: true)
  case .update(_, let deletions, let insertions, let modifications):
    self?.refreshData(reload: false)

    self?.workspaceOutlineView.beginUpdates()

    self?.workspaceOutlineView.insertItems(at: IndexSet(insertions), inParent: nil, withAnimation: .slideDown)
    //--- (!) The crash seems to be on the next line...
    self?.workspaceOutlineView.removeItems(at: IndexSet(deletions), inParent: nil, withAnimation: .slideUp)
    self?.workspaceOutlineView.reloadData(forRowIndexes: IndexSet(modifications), columnIndexes: IndexSet([0]))

    self?.workspaceOutlineView.endUpdates()

  case .error(let error): print("\(error)")
  }
}

在尝试removeItems调用之前,我正在workspaces中刷新我的数据源数组refreshData(),如下所示:

func refreshData(reload: Bool){
  let realm = try! Realm()
  let workspaceObjects = realm.objects(Workspace.self).sorted(byKeyPath: "order", ascending: true)

  workspaces.removeAll()
  workspaces.append(contentsOf: workspaceObjects)

  if reload{
    workspaceOutlineView.reloadData()
  }
}

我无法弄清楚删除对象的访问位置并导致异常。 NSOutlineView似乎仍然在某个地方引用它。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

两件事:

您在观察闭合中的removeItems(...)调用为时已晚。该对象已经失效,但是您通过removeItems(...)调用击中了大纲视图,其中节点仍然引用了失效的对象。

我建议从封闭外部的大纲视图中删除该项目,也许是在处理用户删除请求的action方法中。

第二,您应该查看为removeItems(...)赋予的索引:

.update枚举中从领域中获得的是相对于领域对象的索引。但是,大纲视图方法期望相对于其父级的索引。因此,“平坦”领域结果中的第十个项目可能是相对于其大纲视图中其父节点的第二个项目。

检查outlineView.childIndex(forItem: ...)以获得相对子索引。