gpt4 book ai didi

swift - 从后台线程合并到主线程上下文 : delete order random so crashes NSTableView

转载 作者:搜寻专家 更新时间:2023-11-01 05:32:58 24 4
gpt4 key购买 nike

我在删除后台线程上的多个对象时遇到了麻烦:

func delete(hierarchy: Hierarchy) throws {
// let backgroundThread = self.mainThread
let hierarchies = try self.hierarchies.reloadFrom(context: backgroundThread)

let hierarchy = try hierarchy.reloadFrom(context: backgroundThread)
let hierarchyModel = hierarchy.model!

// .. doing some checks ..

backgroundThread.performAndWait {
backgroundThread.delete(rootFile)
backgroundThread.delete(hierarchyModel)
for (index, model) in hierarchies.model!.hierarchies!.array.enumerated() {
let hierarchyModel = model as! HierarchyModel
hierarchyModel.position = Int32(index)
}

}

try backgroundThread.save()
}

然后循环:

func delete(hierarchies: [Hierarchy]) {
do {
for hierarchy in hierarchies {
try modelController.delete(hierarchy: hierarchy)
}
} catch {
NotificationCenter.default.post(FatalErrorNotification(error: error))
}
}

在保存时,通常的 NSFetchedResultsController 会调用它的委托(delegate)。请注意,他在 mainThread 上工作。

public func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {

print(indexPath, newIndexPath)

switch type {
case .insert:
// ...

case .delete:
tableView.removeRows(at: IndexSet(integer: indexPath!.item), withAnimation: .slideRight)

case .update:
// ...

case .move:
// ...
}
}

我使用 mainThread.automaticallyMergeChangesFromParent 获取从 backgroundThread 到 mainThread 的更改。到目前为止,这对我来说效果很好。
我的问题是在合并过程中会发生这样的事情:

# Merging from background thread, delete order crashes.
Optional([0, 0]) nil
Optional([0, 1]) nil
Optional([0, 2]) nil

在 fetchedResultsController 委托(delegate)调用中崩溃之前。它在第三次调用时崩溃,只剩下 [0, 0] 行要删除。所以它使应用程序崩溃。
如果我在 mainThread 上执行删除操作,则删除操作一个接一个地完成:

# On mainThread: delete order works.
Optional([0, 0]) nil
Optional([0, 2]) Optional([0, 1])
Optional([0, 1]) Optional([0, 0])
going to end updates.
endUpdates
beginUpdates
Optional([0, 0]) nil
Optional([0, 1]) Optional([0, 0])
going to end updates.
endUpdates
beginUpdates
Optional([0, 0]) nil
going to end updates.
endUpdates

不会崩溃。我尝试了什么:

  • 仅在所有三个删除后调用保存,而不是在每个删除后调用。
  • 反转删除的顺序。
  • 更改合并策略(生气)
  • 将整个删除函数包装在 backgroundThread.performAndWait { ... }
  • 试图找到一种方法,使更改在删除之前进入主线程。

一些更多收集的删除命令:

# On background thread: lucky.
beginUpdates
Optional([0, 2]) nil
Optional([0, 1]) nil
Optional([0, 0]) nil
going to end updates.
endUpdates

# On background thread: lucky again.
beginUpdates
Optional([0, 2]) nil
Optional([0, 1]) nil
Optional([0, 0]) nil
going to end updates.
endUpdates

# On background thread: unlucky again.
Optional([0, 1]) nil
Optional([0, 0]) nil
Optional([0, 2]) nil

# On background thread: unlucky again.
Optional([0, 0]) nil
Optional([0, 1]) nil
Optional([0, 2]) nil

# On background thread: unlucky on 2nd delete already.
beginUpdates
Optional([0, 1]) nil
Optional([0, 2]) nil

我希望有人能帮我解决这个问题。真的很感激,我被卡住了。

//
// NSFetchedResultsControllerDelegate
//
public func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
print("beginUpdates")
tableView.beginUpdates()
}
public func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
print("going to end updates.")
tableView.endUpdates()
print("endUpdates")
}

最佳答案

我想我找到了问题所在。您不能在后台线程上删除对象,然后重新排序,然后期望删除以正确的顺序到达主线程。

关于swift - 从后台线程合并到主线程上下文 : delete order random so crashes NSTableView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51344803/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com