使用CoreData获取NSRangeException

时间:2016-08-04 15:25:22

标签: ios swift core-data nsfetchedresultscontroller nsmanagedobject

大家好,你好,

我有以下问题并尝试解决数小时。 感觉就像我的CoreData / FetchResultsController有些不对劲。

我有以下代码:

import UIKit
import CoreData

class SavedActivitiesViewController: UITableViewController, NSFetchedResultsControllerDelegate {

var managedObjectContext: NSManagedObjectContext? = nil



override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.fetchedResultsController.sections!.count ?? 0
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("ActivityCell") as! ActivityCell

    let activity = self.fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject
    self.configureCell(cell, withObject: activity)


    return cell
}

override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return false if you do not want the specified item to be editable.
    return true
}

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {
        let context = self.fetchedResultsController.managedObjectContext
        context.deleteObject(self.fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject)

        do {
            try context.save()
        } catch {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            //print("Unresolved error \(error), \(error.userInfo)")
            abort()
        }
    }
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
    let activityView = self.storyboard?.instantiateViewControllerWithIdentifier("ActivityView") as! ActivityViewController
    let activityViewNav = UINavigationController(rootViewController: activityView)

    let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

    appDelegate.drawerContainer!.centerViewController = activityViewNav
    appDelegate.drawerContainer!.toggleDrawerSide(DrawerSide.Left, animated: true, completion: nil)
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return 80.0
}



func configureCell(cell: UITableViewCell, withObject object: NSManagedObject) {

    let activity = object as! Activity
    let cell = cell as! ActivityCell

    cell.shortTitle.text = activity.valueForKey("shortTitle") as? String

}

// MARK: - Fetched results controller

var fetchedResultsController: NSFetchedResultsController {
    if _fetchedResultsController != nil {
        return _fetchedResultsController!
    }

    let fetchRequest = NSFetchRequest()
    // Edit the entity name as appropriate.
    let entity = NSEntityDescription.entityForName("Activity", inManagedObjectContext: self.managedObjectContext!)
    fetchRequest.entity = entity

    // Set the batch size to a suitable number.
    fetchRequest.fetchBatchSize = 20

    // Edit the sort key as appropriate.
    let sortDescriptor = NSSortDescriptor(key: "activityID", ascending: false)

    fetchRequest.sortDescriptors = [sortDescriptor]

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: nil, cacheName: "Master")
    aFetchedResultsController.delegate = self
    _fetchedResultsController = aFetchedResultsController

    do {
        try _fetchedResultsController!.performFetch()
    } catch {
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        //print("Unresolved error \(error), \(error.userInfo)")
        abort()
    }

    return _fetchedResultsController!
}
var _fetchedResultsController: NSFetchedResultsController? = nil

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:
        tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
    case .Delete:
        tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
    case .Update:
        self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, withObject: anObject as! NSManagedObject)
    case .Move:
        tableView.moveRowAtIndexPath(indexPath!, toIndexPath: newIndexPath!)
    }
}

func controllerDidChangeContent(controller: NSFetchedResultsController) {
    self.tableView.endUpdates()
}

出于某种原因,我的应用程序会在启动时崩溃:

2016-08-04 16:47:29.546 TestApp [2527:852314] *由于未捕获的异常'NSRangeException'而终止应用程序,原因:'* - [_ PFBatchFaultingArray objectAtIndex:]:index( 0)超出界限(0)' ***首先抛出调用堆栈:

...

libc ++ abi.dylib:以NSException类型的未捕获异常终止 (LLDB)

如果我为其中断的所有异常启用了断点:

let activity = self.fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject
使用cellForRowAtIndexPath

的tableView方法中的

当我打印self.fetchedResultsController.sections!.count它说1但是当我不保存任何内容时,它不应该打印0吗? (我在模拟器上删除了应用程序,因此我的CoreData应该被删除)

当我设置

的返回时

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.fetchedResultsController.sections!.count ?? 0 }

到0我的应用程序正在运行。如果我现在通过App将对象保存到我的coreData中,我可以将返回设置回return self.fetchedResultsController.sections!.count ?? 0 它又重新开始了。但我只能保存这一个对象。 我收到以下消息:

2016-08-04 17:14:40.407 TestApp [2582:984402] ***断言失败 - [UITableView _endCellAnimationsWithContext:],/ BuildRoot / Library / Cache / com.apple.xbs / Source / UIKit_Sim / UIKit -3512.60.7 / UITableView.m:1502 2016-08-04 17:14:40.408 TestApp [2582:984402] CoreData:错误:严重的应用程序错误。在调用-controllerDidChangeContent:期间,从NSFetchedResultsController的委托中捕获到异常。尝试将第10行插入第0部分,但在使用userInfo(null)更新后第0部分中只有1行

第10行来自多次点击“保存”按钮。 我不知道自己做错了什么,我使用了一本解释coreData的书,并将其与互联网上的例子进行了比较。

你们是我最后的希望。

0 个答案:

没有答案