从TableViewCell中的UISwitch更新核心数据

问题描述:

我有一个绑定到一些Core Data值的静态表,我不确定在这种情况下我将如何使用NSFetchedResultsController,尽管我已经看到关于多推荐多少的讨论是。从TableViewCell中的UISwitch更新核心数据

我抓住我的Core Data对象,它通过Segue传递。

我也有一个设置为包含问题的模型,其中一个属性包含Core Data值(这就是为什么我不认为我可以使用NSFetchedResultsController,因为即使我的Core Data实体包含一些我需要的价值观,我不知道我需要一个完整的数据集)

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

的问题是调查相关的诸如“你的财产X?”与映射到Core DataUiSwitch

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我需要它来更新核心数据值,并重新装载表,它挂接到一个CustomTableViewCell像这样:

*编辑 - 几乎得到这个东西的工作!我的继承人UITableViewCell

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() 

     } 

     } 

我可以明显地访问其中的切换触发位,但此类不知道的核心数据位什么的,我想使用的通知,但只是似乎有点乱...

+0

你是说,当你在桌子上的一排切换开关,要重新加载整个表?你有什么改变? – Russell

+0

UISwitch被绑定到一个Core Data值,当它改变时它需要更新Core Data实体并重新加载表格,因为这些布尔值有一些额外的逻辑,例如当一个开关在表格上改变时,另一个行需要消失 – dyatesupnorth

+0

好吧 - 我知道你理论上可以通过self.superview获得单元格的父类,但是你可能会更好地将对tableview的引用存储为自定义单元类的一部分! 我已经更新了我的答案,只是为了保持在一个地方 – Russell

当你创建你的细胞,传递到coredata对象的引用,和的tableView本身并存储为SurveyQuestionTableViewCell的属性,那么您可以在您的自定义你需要在的setSelected()一切

电池类,添加属性的问题

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() 
+0

你有一个如何传递参考的例子吗? – dyatesupnorth

+0

对不起,我不明白,我的单元格定义中的下落?你的意思是类,即。SurveyQuestionTableViewCell:UITableViewCell还是在cellForRowAtIndexPath函数内部? – dyatesupnorth

+0

我已更新答案 – Russell

尝试使用此代码:

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") } 
+0

但不应该SurveyQuestionTabelViewCell不知道任何关于核心数据对象,我认为这种事情是不好的做法? – dyatesupnorth

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

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 
} 

然后在任何c姑娘这需要这个数据模型

var dataModel = DataModelInstance.sharedInstance 

我知道有访问那些谁只是永远不会使用单身,但它可以是一个更好的解决方案,以使这些属性提供需要的地方去

使用共享数据模型,您可以简单地将所有数据属性移出它们当前所在的类,并通过数据模型引用它们 - 然后,如果您在自定义单元类中具有相同的数据模型,则可以执行无论你在主视图中能做什么。为了使您的GUI和处理逻辑独立的,你可以把一切都在数据模型

dataModel.refreshTable() 

,然后定义数据模型,把你的表视图的护理有关的功能 - 你可以目前所有的编辑内容保存到数据,并重新加载,而不必将任何逻辑放入单独的单元类中

+0

看起来像一个更清洁的方法,虽然我是在这个项目的时刻,兔子洞有点太远了,是否有任何教程项目使用这种方法?就这样我可以看到一个项目将如何整体放在一起? – dyatesupnorth

+1

看起来像你'\可能是正确的。我找不到任何包含单例和数据库的单个教程,但有很多关于如何实现单例的教程,我认为最新版本的swift可能已经简化了更多http:/ /codereview.stackexchange.com/questions/80246/swift-1-2-singleton-implementation – Russell

您必须在闭包中使用[unowned self] in。见Apple's docs。这是如何完成的。另请参阅CoreDataKit,这是一款28星级github回购核心数据堆栈。它可以在cocoapods上使用,说实话,为什么不把这样的东西放到你的应用程序中,而不用担心“无主的自我”和其他哲学的大脑旋转,呃?

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


         }) 
        }