从 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)!)
}
})
}
我有一个绑定到某些 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)!)
}
})
}