(Swift)使用NSFetchedResultsController在indexPathFOrSelectedRow中编辑保存的数据 [英] (Swift) Edit saved data at indexPathFOrSelectedRow using NSFetchedResultsController

查看:484
本文介绍了(Swift)使用NSFetchedResultsController在indexPathFOrSelectedRow中编辑保存的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a UITableViewController and a ordinary ViewController. In the VC (named nyTankning) there the user will type in info that is saved to a Core Data database. The database is loaded and displayed in the UITableVieController.

现在我想要编辑保存在数据库中的信息。我搜索的答案,但我没有发现任何有用的,因为我使用NSFetchedResultsController后下面将核心数据检索到tableview单元格swift

Now I want to be able to edit the info that is saved in the database. I have searched for the answer, but I haven´t found anything helpful, because I have used NSFetchedResultsController after following retrieving core data into tableview cells swift

现在我在TableViewController中编写的代码看起来像这样:

Right now the code that I have wrote in the TableViewController looks like this:

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没有正确写。

But I understand from the Debugger that the indexPath is not written properly.


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

2015-01-16 17:14:22.207 TankApp[4232:241135] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSIndexPath objectID]: unrecognized selector sent to instance 0x7c274660'

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

Here is the full code for the whole 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
    }
}

}

推荐答案

我这样使用三元运算符来处理解包可选索引路径的情况,但如果let 工作,以避免可能发生的任何崩溃。此外,我建议使用 indexPathForCell 并使用 sender 作为您的单元格,而不是 indexPathForSelectedRow

I accomplish it like this using the ternary operator to handle the case for unwrapping the optional index path, but if let works just as well to avoid any crashes that may occur from that. Also, I would suggest using indexPathForCell and using sender as your cell rather than 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
    }
}

管理对象到下一个视图控制器,并在其中处理它。如果你想从这个方法中维护设置所有的目标类变量,你可以使用如果let 解开可选的索引路径,如下所示:

With this method, you pass the entire managed object to the next view controller where you handle that accordingly. If you want to maintain setting all the destinations class variables from this method, you use if let to unwrap the optional index path like so:

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
        }
    }
}

在此处查看示例GitHub项目

这篇关于(Swift)使用NSFetchedResultsController在indexPathFOrSelectedRow中编辑保存的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆