从 TableViewCell 中的 UISwitch 更新核心数据

Update Core Data from a UISwitch inside a TableViewCell

我有一个绑定到某些 Core Data 值的静态 table,我不确定在这种情况下我将如何使用 NSFetchedResultsController,尽管我已经看到有关的讨论更推荐多少。

我抓取通过 Segue 传递的 Core Data 对象。

我还有一个模型设置为包含问题,其中一个属性包含 Core Data 值(这就是为什么我不认为我可以使用 NSFetchedResultsController,因为即使虽然我的核心数据实体包含一些我需要的值,但我不确定我是否需要完整的数据集)

self.surveyQuestion.append(SurveyQuestion(question: "Does the customer have a 'Proof of ownership'?", answer: coreDataEntity.isProofOfOwnership as Bool))

问题与调查相关,例如 "Is your property X?" 带有映射到 Core Data 值的 UiSwitch

 override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    // Configure the cell...
    let cell : SurveyQuestionTableViewCell = tableView.dequeueReusableCellWithIdentifier("SurveyQuestionCell") as! SurveyQuestionTableViewCell

    cell.lblQuestion.textColor = UIColor.grayColor()

    let surveyQuestion = self.surveyQuestion[indexPath.row]
    cell.lblQuestion.text = surveyQuestion.question
    cell.toggQuestion.on = surveyQuestion.answer
    if cell.toggQuestion.on {
                   cell.lblQuestion.textColor = UIColor.blackColor()
    cell.accessoryType = .DetailDisclosureButton
    }

    return cell
}

现在,当我点击 UISwitch 时,我需要它来更新核心数据值,并重新加载 table,它连接到 CustomTableViewCell,如下所示:

*edit - 几乎让这个东西工作了!这是我的 UITableViewCell class

 class SurveyQuestionTableViewCell: UITableViewCell {


    let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext

    @IBOutlet weak var lblQuestion: UILabel!

    @IBOutlet weak var toggQuestion: UISwitch!
    var surveyQuestionReference : SurveyQuestion?
    var tableViewReference : UITableView?

    @IBAction func toggledQuestion(sender: AnyObject) {
        let tempContext: NSManagedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
        tempContext.parentContext = self.managedObjectContext

        tempContext.performBlock({
            let entityName = "CoreDataEntity"
            let request = NSFetchRequest(entityName: entityName)
            request.predicate = NSPredicate(format: "id = %@", self.surveyQuestionReference!.id)
            do {

                let results = try tempContext.executeFetchRequest(request) as? [NSManagedObject]

                if results!.count > 0{

                        if let moc = self.managedObjectContext{
                            moc.performBlockAndWait({



                                for result in results!{
                                   result.setValue(self.toggQuestion.on, forKey: (self.surveyQuestionReference?.property)!)
                                }



                            })





                    }
                }
                do {
                    try tempContext.save()

                    //completion(finished: true)
                } catch let error {
                    print(error)
                }
            }catch{
                print("error")
            }

        })
        print(sender)
        dispatch_async(dispatch_get_main_queue()) {
          self.tableViewReference!.reloadData()

        }

        }

我显然可以访问触发切换的位,但是这个 class 对核心数据位一无所知,我正在考虑使用通知,但这看起来有点混乱.. .

当您创建单元格时,传入对 coredata 对象的引用和 tableView 本身并将它们存储为 SurveyQuestionTableViewCell 的属性,然后您可以在 setSelected()

中执行您需要的所有操作

在您的自定义单元格 class 中,为问题添加一个属性

class SurveyQuestionTableViewCell: UITableViewCell {

    @IBOutlet weak var lblQuestion: UILabel!

    @IBOutlet weak var toggQuestion: UISwitch!

    var surveyQuestionReference : SurveyQuestionType
    vat tableViewReference : UITableView
    ...

然后在创建单元格后在 cellForRowAtIndexPath 中

cell.surveyQuestionReference = surveyQuestion
cell.tableViewReference = tableView

其中 SurveyQuestionType 是您之前定义的任何内容

在setSelected中,你可以使用那些存储的属性

surveyQuestionReference = self.toggQuestion.on
tableViewReference.reloadData()

要更新核心数据中的任何记录,请尝试使用此代码:

let managedObjectContext:NSManagedObjectContext=(UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext!
let req=NSFetchRequest(entityName: "Entity Name")
req.returnsObjectsAsFaults=false
let result:NSArray=try! managedObjectContext.executeFetchRequest(req)

if result.count>0{

let res=result[Int(indexPath.row!]as! NSManagedObject
res.setValue("The Value", forKey: "Key Name")
 do {
     try managedObjectContext.save()
     } catch _ { print("Update Unsuccessful") }

这是另一个选项,使用共享实例

import Foundation
import MapKit
import CoreData


class DataModelInstance : NSObject, NSCoding
{
    var appDelegate         : AppDelegate?
    var managedContext      : NSManagedObjectContext?
    var persistentStoreCoordinator         : NSPersistentStoreCoordinator?

    // plus whatever else you need

class var sharedInstance : DataModelInstance
{
    struct Singleton
    {
        static let instance = DataModelInstance()
    }


    return Singleton.instance
}

然后在任何需要访问此数据模型的class中

var dataModel = DataModelInstance.sharedInstance

我知道有些人永远不会使用单例,但它可以是一种更优雅的解决方案,可以让这些属性在需要的地方可用

使用共享数据模型,您只需将所有数据属性从它们当前所在的 class 中移出,并通过数据模型引用它们 - 那么如果您在其中具有相同的数据模型您的自定义单元格 class,您可以在主视图中执行任何操作。为了让你的 GUI 和处理逻辑分开,你可以把所有的东西都放在数据模型中

dataModel.refreshTable()

然后在数据模型中定义一个函数来处理您的 table 视图 - 您可以保存所有当前对数据的编辑,然后重新加载,而不必将任何逻辑放在单个单元格中classes

您必须在闭包中使用 [unowned self] in。请参阅 Apple's docs. This is how it's done. See also CoreDataKit,一个 28 星 github 核心数据堆栈回购协议。它在 cocoapods 上可用,老实说,为什么不把这样的东西放到你的应用程序中而不用担心 "unowned selves" 和其他哲学上的脑筋急转弯,嗯?

if let moc = self.managedObjectContext{
                        moc.performBlockAndWait({

                            /* In here we are in a closure (Swift version of a block), so "self" is problematic. Use unowned self instead (in objective c you'd have to do weak self). */
                            [unowned self] in
                            for result in results!{
                               result.setValue(self.toggQuestion.on, 
                                      forKey: (self.surveyQuestionReference?.property)!)
                            }


                        })
                    }