Mat*_*ong 9 core-data uitableview nsfetchedresultscontroller swift
全屏桌面视图仅适用于iPad的应用程序.我已启用滑动以删除我的行.删除后(rowEditingStyle完成)行动画总是结束,但有时整个表视图会冻结.请注意,不是整个UI,因此它不是一个被阻止的主线程.我可以点击列标题或点击导航控制器上的后退按钮,但表本身会锁定并且无法刷卡.我可以通过点击我的一个列标题按钮来解冻它.
我完全不知道可能导致冻结的原因.我正在使用NSFetchedResultsController,这是我的委托代码.它是漂亮的锅炉板(更新:现在不是锅炉板.使用批处理方法):
// MARK: NSFetchedResultsController delegate methods
lazy var deletedSectionIndexes : NSMutableIndexSet = {
return NSMutableIndexSet()
}()
lazy var insertedSectionIndexes : NSMutableIndexSet = {
return NSMutableIndexSet()
}()
lazy var deletedRowIndexPaths : [NSIndexPath] = {
return [NSIndexPath]()
}()
lazy var insertedRowIndexPaths : [NSIndexPath] = {
return [NSIndexPath]()
}()
lazy var updatedRowIndexPaths : [NSIndexPath] = {
return [NSIndexPath]()
}()
func controllerWillChangeContent(controller: NSFetchedResultsController) {
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch(type) {
case .Delete:
if let indexPath = indexPath {
self.deletedRowIndexPaths.appendDistinct(indexPath)
}
case .Update:
if let indexPath = indexPath {
self.updatedRowIndexPaths.appendDistinct(indexPath)
}
case .Insert:
if let newIndexPath = newIndexPath {
self.insertedRowIndexPaths.appendDistinct(newIndexPath)
}
case .Move:
if let indexPath = indexPath, newIndexPath = newIndexPath {
self.insertedRowIndexPaths.appendDistinct(newIndexPath)
self.deletedRowIndexPaths.appendDistinct(indexPath)
}
}
}
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
switch(type) {
case .Delete:
self.deletedSectionIndexes.addIndex(sectionIndex)
case .Insert:
self.insertedSectionIndexes.addIndex(sectionIndex)
default:
break
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
self.tableView.beginUpdates()
self.tableView.insertSections(self.insertedSectionIndexes, withRowAnimation: .None)
self.tableView.deleteSections(self.deletedSectionIndexes, withRowAnimation: .None)
self.tableView.insertRowsAtIndexPaths(self.insertedRowIndexPaths, withRowAnimation: .None)
self.tableView.deleteRowsAtIndexPaths(self.deletedRowIndexPaths, withRowAnimation: .None)
self.tableView.reloadRowsAtIndexPaths(self.updatedRowIndexPaths, withRowAnimation: .None)
self.tableView.endUpdates()
self.insertedSectionIndexes.removeAllIndexes()
self.deletedSectionIndexes.removeAllIndexes()
self.deletedRowIndexPaths.removeAll()
self.insertedRowIndexPaths.removeAll()
self.updatedRowIndexPaths.removeAll()
}
Run Code Online (Sandbox Code Playgroud)
删除在didChangeObject委托方法中被调用,但是,从技术上讲,它不是真正的删除.我只是将一个属性设置为-1,然后通过NSMangagedObjectContext保存该元素 - 此时NSFRC似乎做了正确的事情,将其从使用此谓词获取的获取对象列表中删除:
NSPredicate(format: "account = %@ and quantity != -1", account)
Run Code Online (Sandbox Code Playgroud)
哪里account是有效的帐户管理对象.该行消失90%或更多时间没有问题.事实上,在动画完成后,桌子冻结在我所描述的庄园中.它永远不会冻结删除按钮仍然显示,所以我知道它是在调用commitEditingStyle之后.删除按钮没有自定义实现.它是要删除的滑动的默认UITableView实现.这是我的commitEditingStyle方法:
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
if let frameboardItem = self.fetchedResultsController.objectAtIndexPath(indexPath) as? IRMFrameBoardItemMO {
if frameboardItem.isNew {
// If it's never been pushed to the server, just delete locally. This will trigger a table reload
// via NSFetchedResultsController
DataManager.mainContext.deleteObject(frameboardItem)
} else {
// Otherwise mark it with a negative quantity which tells the server to delete it and tells the
// app to hide it.
frameboardItem.quantity = -1
}
do {
try DataManager.mainContext.save()
} catch let error as NSError {
dLog("Something went wrong: \(error.localizedDescription)")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
你可以在这里看到我正在谈论的视频.它超过两分钟,所以你可能不想看整件事,但我会把它放在这里供参考.
很想听听任何建议.
更新
我更新了NSFRC委托方法以使用批处理方法来确保一次性应用所有更新.这还没有解决问题.桌子还会定期冻结.
对于这个问题我也有猜测。我的想法是,controllerDidChangeContent可以被调用两次或更多次,并且比表刷新更快,并且多次调用的原因tableView.beginUpdates()可能会挂起表。
因此,为了解决这个问题,我建议将更新包装在dispatch_async块中,或者只是简单的布尔标志
func controllerDidChangeContent(controller: NSFetchedResultsController) {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.beginUpdates()
// ..... rest of update code
self.updatedRowIndexPaths.removeAll()
})
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
931 次 |
| 最近记录: |