首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSFetchedResultsController XCode 7期

NSFetchedResultsController XCode 7期
EN

Stack Overflow用户
提问于 2015-08-31 19:57:40
回答 3查看 2.8K关注 0票数 9

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中设置要调试的断点

代码语言:javascript
复制
//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部分,我也尝试调用

代码语言:javascript
复制
 self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!)

配置单元方法:

代码语言:javascript
复制
func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) { 
   let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Person 
   //etc 
} 

排序描述符

代码语言:javascript
复制
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

代码语言:javascript
复制
Update New: Optional(<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}) Old: Optional(<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0})

XCode 7b6 iOS 8.4

代码语言:javascript
复制
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)
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-09-01 16:46:19

我试过几件事,我相信这是个错误。正如您从我的日志中看到的,即使我更新了现有记录,委托也会获得插入消息。在.Insert添加条件检查解决了我的问题。我不会在桌子上使用任何移动操作。因此,同样的条件操作也是必要的,如果您正在使用.Move,我的当前代码如下所示

代码语言:javascript
复制
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)
    }
}

我试图更新单个记录,多个记录,到目前为止我还没有看到任何崩溃。我在用

代码语言:javascript
复制
tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)

方法,但

代码语言:javascript
复制
self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!)

在我的测试中也起了作用。

票数 10
EN

Stack Overflow用户

发布于 2015-09-01 16:04:58

在使用Xcode 7 beta 6在Sim/Device < iOS9上运行时,这种情况似乎发生在我身上:

代码语言:javascript
复制
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

一种可能的解决方法是不对更改进行动画化(直到此更改得到修复):

代码语言:javascript
复制
//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()
}
票数 1
EN

Stack Overflow用户

发布于 2015-10-23 01:47:44

当我在SDK 9.1上构建时,我再也没有看到这个问题了。看来窃听器已经修好了。你可以试试。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32318976

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档