首页 文章

(Swift)使用NSFetchedResultsController在indexPathFOrSelectedRow编辑保存的数据

提问于
浏览
0

我有一个UITableViewController和一个普通的ViewController . 在VC(名为nyTankning)中,用户将键入保存到Core Data数据库的信息 . 数据库被加载并显示在UITableVieController中 .

现在我希望能够编辑保存在数据库中的信息 . 我已经找到了答案,但我还没有找到任何有用的东西,因为我在使用了以下retrieving core data into tableview cells swift后使用了NSFetchedResultsController

现在我在TableViewController中编写的代码如下所示:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.

    if segue.identifier == "update" {
        let indexPath = self.tableView.indexPathForSelectedRow()
        let selectedCell = fetchedResultsController?.indexPathForObject(indexPath!) as? NSManagedObject
        let nyTankning: nyTankningViewController = segue.destinationViewController as nyTankningViewController

        nyTankning.liter = selectedCell?.valueForKey("liter") as String
        nyTankning.kronor = selectedCell?.valueForKey("kronor") as String
        nyTankning.exisitingTankning = selectedCell


    }

但是我从调试器中了解到indexPath没有正确编写 .

2015-01-16 17:14:22.207 TankApp [4232:241135] ***由于未捕获的异常'NSInvalidArgumentException'终止应用程序,原因:' - [NSIndexPath objectID]:无法识别的选择器发送到实例0x7c274660'

编辑:这是整个UITableViewController的完整代码:

import Foundation
import UIKit
import CoreData

class tankningarTableViewController: UITableViewController, NSFetchedResultsControllerDelegate {

var firstTime = 0

let managedObjectContext: NSManagedObjectContext? = (UIApplication.sharedApplication().delegate as? AppDelegate)?.managedObjectContext

var fetchedResultsController: NSFetchedResultsController?


override func viewDidLoad() {
    super.viewDidLoad()


    fetchedResultsController = NSFetchedResultsController(fetchRequest: allaTankningarFetchRequest(), managedObjectContext: managedObjectContext!, sectionNameKeyPath: nil, cacheName: nil)
    fetchedResultsController?.delegate = self
    fetchedResultsController?.performFetch(nil)


}

func alertViewFirstTime() {
    let alertController = UIAlertController(title: "TankApp", message:
        "Du kan lägga till en ny tankning genom att trycka på plusknappen (+).", preferredStyle: UIAlertControllerStyle.Alert)
    alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default,handler: nil))

    self.presentViewController(alertController, animated: true, completion: nil)
}

func allaTankningarFetchRequest() -> NSFetchRequest {

    var fetchRequest = NSFetchRequest(entityName: "Tankningslista")
    let sortDescriptor = NSSortDescriptor(key: "datum", ascending: false)

    fetchRequest.predicate = nil
    fetchRequest.sortDescriptors = [sortDescriptor]
    fetchRequest.fetchBatchSize = 20

    return fetchRequest
}


override func viewDidAppear(animated: Bool) {


    if firstTime == 0 {
        alertViewFirstTime()
        firstTime++

    }
    else {
        return
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete method implementation.
    // Return the number of rows in the section. 
    return fetchedResultsController?.sections?[section].numberOfObjects ?? 0
}


//MARK: NSFetchedResultsController Delegate Functions
func controllerWillChangeContent(controller: NSFetchedResultsController) {
    tableView.beginUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {

    switch type {
    case NSFetchedResultsChangeType.Insert:
        tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade)
        break
    case NSFetchedResultsChangeType.Delete:
        tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade)
        break
    case NSFetchedResultsChangeType.Move:
        break
    case NSFetchedResultsChangeType.Update:
        break
    default:
        break
    }
}

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {
    }

    switch editingStyle {
    case .Delete:
        managedObjectContext?.deleteObject(fetchedResultsController?.objectAtIndexPath(indexPath) as Model)
        managedObjectContext?.save(nil)
    case .Insert:
        break
    case .None:
        break
    }

}

func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {

    switch type {
    case NSFetchedResultsChangeType.Insert:
        tableView.insertRowsAtIndexPaths(NSArray(object: newIndexPath!), withRowAnimation: UITableViewRowAnimation.Fade)
        break
    case NSFetchedResultsChangeType.Delete:
        tableView.deleteRowsAtIndexPaths(NSArray(object: indexPath!), withRowAnimation: UITableViewRowAnimation.Fade)
        break
    case NSFetchedResultsChangeType.Move:
        tableView.deleteRowsAtIndexPaths(NSArray(object: indexPath!), withRowAnimation: UITableViewRowAnimation.Fade)
        tableView.insertRowsAtIndexPaths(NSArray(object: newIndexPath!), withRowAnimation: UITableViewRowAnimation.Fade)
        break
    case NSFetchedResultsChangeType.Update:
        tableView.cellForRowAtIndexPath(indexPath!)
        break
    default:
        break
    }
}

func controllerDidChangeContent(controller: NSFetchedResultsController) {
    tableView.endUpdates()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    // Configure the cell...

    let CellID: NSString = "Cell"

    var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(CellID) as UITableViewCell


    let fetchRequest = NSFetchRequest(entityName: "Tankningslista")

    if let cellContact = fetchedResultsController?.objectAtIndexPath(indexPath) as? Model {
        cell.textLabel?.text = "\(cellContact.datum)"
        cell.detailTextLabel?.text = "\(cellContact.liter) Liter, \(cellContact.kronor) Kronor, \(cellContact.literpris) Kronor/Liter"

    }

    return cell
}
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return NO if you do not want the specified item to be editable.
    return true
}
*/

/*
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {
        // Delete the row from the data source
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
    } else if editingStyle == .Insert {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }    
}
*/

/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {

}
*/

/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return NO if you do not want the item to be re-orderable.
    return true
}
*/

// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "update" {
        let destination = segue.destinationViewController as nyTankningViewController
        let indexPath = self.tableView.indexPathForCell(sender as Model)

        destination.event = indexPath != nil ? fetchedResultsController.objectAtIndexPath(indexPath!) as? NSManagedObject : nil
    }
}

}

1 回答

  • 1

    我使用三元运算符来处理打开可选索引路径的情况,但是 if let 也能正常工作以避免因此而发生的任何崩溃 . 另外,我建议使用 indexPathForCell 并使用 sender 作为您的单元而不是 indexPathForSelectedRow .

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
        if segue.identifier == "SomeSegue" {
            let destination = segue.destinationViewController as SomeViewController
            let indexPath = self.tableView?.indexPathForCell(sender as SomeCell)
    
            destination.event = indexPath != nil ? fetchedResultsController?.objectAtIndexPath(indexPath!) as? NSManagedObject : nil
        }
    }
    

    使用此方法,您将整个托管对象传递到下一个视图控制器,您可以在其中相应地处理它 . 如果要维护此方法中的所有目标类变量的设置,可以使用 if let 来打开可选的索引路径,如下所示:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
        if segue.identifier == "SomeSegue" {
            let destination = segue.destinationViewController as SomeViewController
            if let indexPath = self.tableView?.indexPathForCell(sender as SomeCell) {
                let object = fetchedResultsController?.objectAtIndexPath(indexPath) as? NSManagedObject
                destination.foo = object?.bar
            }
        }
    }
    

    See a sample GitHub project here.

相关问题