Xcode 7、beta 6和NSFetchedResultsController今天让我头疼。如果我用Xcode 6编译相同的代码(使用Swift 2补丁),程序可以在设备和模拟器(iOS 7,iOS8)上工作。但是,如果我使用Xcode 7 beta 6编译,每当我更新iOS数据时,程序就会在设备上崩溃( 8.4),其中包含以下错误消息。
我得到了一个类似于下面的错误
CoreData:错误:严重的应用程序错误。在调用NSFetchedResultsController :时,从-controllerDidChangeContent的委托中捕获了一个异常。无效更新:第0节中的行数无效。更新(2)之后包含在现有节中的行数必须等于更新(2)之前包含在该节中的行数,加上或减去从该节插入或删除的行数(2插入,1删除),加上或减去移动到或移出该节的行数(0移动,0移出)。使用userInfo (null)
有时,它会以另一个错误崩溃,例如
无效指针从空闲列表中退出队列*在malloc_error_break中设置要调试的断点
//NSFetchedResultsController delegates
func controllerWillChangeContent(controller: NSFetchedResultsController) {
self.tableView.beginUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
switch type {
case .Insert:
self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
case .Delete:
self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
default:
return
}
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
print("Insert New: \(newIndexPath) Old: \(indexPath)")
tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
case .Delete:
print("Delete New: \(newIndexPath) Old: \(indexPath)")
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
case .Update:
print("Update New: \(newIndexPath) Old: \(indexPath)")
tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
//self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!)
case .Move:
print("Move New: \(newIndexPath) Old: \(indexPath)")
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
self.tableView.endUpdates()
}对于.Update部分,我也尝试调用
self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!)配置单元方法:
func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Person
//etc
} 排序描述符
let sortDescriptor = NSSortDescriptor(key: "date", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]程序总是崩溃。阻止此问题的唯一方法是将delagete设置为0,更新对象,并将delagate设置为self。
这是个虫子吗?如果不是,我怎样才能防止这种情况发生呢?谢谢
一些有相同/相似问题的错误报告
https://forums.developer.apple.com/thread/12184
https://forums.developer.apple.com/thread/4999
iOS 9 - "attempt to delete and reload the same index path"
我运行了XCode6和XCode7版本,并打印了didChangeObject方法--这里是比较
XCode6 iOS 8.4
Update New: Optional(<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}) Old: Optional(<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0})XCode 7b6 iOS 8.4
Update New: nil Old: Optional(<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0})
Insert New: Optional(<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}) Old: Optional(<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0})
2015-09-01 01:15:37.898 TestProg[3230:200562] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit/UIKit-3347.44.2/UITableView.m:1623
2015-09-01 01:15:37.900 TestProg[3230:200562] CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (3) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null)发布于 2015-09-01 16:46:19
我试过几件事,我相信这是个错误。正如您从我的日志中看到的,即使我更新了现有记录,委托也会获得插入消息。在.Insert添加条件检查解决了我的问题。我不会在桌子上使用任何移动操作。因此,同样的条件操作也是必要的,如果您正在使用.Move,我的当前代码如下所示
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
//FIXME: iOS 9 Bug!
if indexPath != newIndexPath {
tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
}
case .Delete:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
case .Update:
tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
// self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!)
case .Move:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
}
}我试图更新单个记录,多个记录,到目前为止我还没有看到任何崩溃。我在用
tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)方法,但
self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!)在我的测试中也起了作用。
发布于 2015-09-01 16:04:58
在使用Xcode 7 beta 6在Sim/Device < iOS9上运行时,这种情况似乎发生在我身上:
2015-09-01 11:39:05.683 Diabetes Pal[15038:245613] *** Assertion failure in
-[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-3347.44.2/UITableView.m:1623
2015-09-01 11:39:14.954 Diabetes Pal[15038:245613] CoreData: error: Serious application error.
An exception was caught from the delegate of NSFetchedResultsController during a call to
-controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (4) must be equal to the number of rows contained in that section before the update (4), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null)
Diabetes Pal(15038,0x33291d4) malloc: *** mach_vm_map(size=1048576) failed (error code=3)
*** error: can't allocate region securely
*** set a breakpoint in malloc_error_break to debug一种可能的解决方法是不对更改进行动画化(直到此更改得到修复):
//MARK: - fetched results controller delegate
func controllerWillChangeContent(controller: NSFetchedResultsController) {
let ios9 = NSOperatingSystemVersion(majorVersion: 9, minorVersion: 0, patchVersion: 0)
if NSProcessInfo().isOperatingSystemAtLeastVersion(ios9) {
tableView?.beginUpdates()
}
}
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
let ios9 = NSOperatingSystemVersion(majorVersion: 9, minorVersion: 0, patchVersion: 0)
if NSProcessInfo().isOperatingSystemAtLeastVersion(ios9) == false {
return
} //[... rest of delegate implementation ...]
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
let ios9 = NSOperatingSystemVersion(majorVersion: 9, minorVersion: 0, patchVersion: 0)
if NSProcessInfo().isOperatingSystemAtLeastVersion(ios9) == false {
return
}//[... rest of delegate implementation ...]
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
let ios9 = NSOperatingSystemVersion(majorVersion: 9, minorVersion: 0, patchVersion: 0)
if NSProcessInfo().isOperatingSystemAtLeastVersion(ios9) == false {
tableView?.reloadData()
return
}
tableView?.endUpdates()
}发布于 2015-10-23 01:47:44
当我在SDK 9.1上构建时,我再也没有看到这个问题了。看来窃听器已经修好了。你可以试试。
https://stackoverflow.com/questions/32318976
复制相似问题