Reputation: 19954
I'd like to update a record in my database but I can't figure out how. Specifically I am trying to fetch a record and then update/save that record with a new value when a user taps the UISwitch.
the method where I am attempting this is in my ViewController.Swift and is called
didChangeSwitchState(#sender: SettingCell, isOn: Bool)
I am using the boiler plate CoreData template which puts the managedObjectContext in the AppDelegate.
this is my model:
and the resulting code plus a method for creating new entries:
LogItem.swift
class LogItem: NSManagedObject {
@NSManaged var settingLabel: String
@NSManaged var switchState: Bool
class func createInManagedObjectContext(moc: NSManagedObjectContext, label: String, state: Bool) -> LogItem {
let newItem = NSEntityDescription.insertNewObjectForEntityForName("LogItem", inManagedObjectContext: moc) as! LogItem
newItem.settingLabel = label
newItem.switchState = state
return newItem
}
}
ViewController.swift
class ViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate, SettingCellDelegate {
// Retreive the managedObjectContext from AppDelegate
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
// Create the table view as soon as this class loads
//var logTableView = UITableView(frame: CGRectZero, style: .Plain)
var logItems = [LogItem]()
override func viewDidLoad() {
super.viewDidLoad()
if let moc = self.managedObjectContext {
let fetchRequest = NSFetchRequest(entityName:"LogItem")
var error: NSError?
let fetchedResults = moc.executeFetchRequest(fetchRequest, error: &error) as! [NSManagedObject]?
if (fetchedResults?.count == 0) {
// Create some dummy data to work with
var items = [
("Best Animal", true),
("Best Language", true),
("Derp", false),
("Applesauce", false)
]
for (settingLabel, switchState) in items {
LogItem.createInManagedObjectContext(moc,
label: settingLabel, state: switchState)
}
} else {
println("data already exists")
}
fetchLog()
}
}
func fetchLog() {
let fetchRequest = NSFetchRequest(entityName: "LogItem")
let sortDescriptor = NSSortDescriptor(key: "settingLabel", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
if let fetchResults = managedObjectContext!.executeFetchRequest(fetchRequest, error: nil) as? [LogItem] {
logItems = fetchResults // question... this seems like it would store the entire table as one item in the array... huh?
}
}
func save() {
var error : NSError?
if(managedObjectContext!.save(&error) ) {
println(error?.localizedDescription)
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let logItem = logItems[indexPath.row]
println(logItem.switchState)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomSettingCell") as! SettingCell
let logItem = logItems[indexPath.row]
cell.settingsLabel?.text = logItem.settingLabel
cell.settingsSwitch.on = logItem.switchState
cell.cellDelegate = self
return cell
}
func didChangeSwitchState(#sender: SettingCell, isOn: Bool) {
let indexPath = self.tableView.indexPathForCell(sender)
managedObjectContext!.save(nil)
var context = managedObjectContext
let fetchRequest = NSFetchRequest()
var entityName = NSEntityDescription.entityForName("LogItem", inManagedObjectContext: self.managedObjectContext!)
fetchRequest.entity = entityName
var error: NSError?
if let cellName = sender.settingsLabel.text {
fetchRequest.predicate = NSPredicate(format: "settingLabel = %@", cellName)
}
var fetchedResults = managedObjectContext!.executeFetchRequest(fetchRequest, error: &error) as? [LogItem]
if let setting = fetchedResults {
if error != nil {
println("An error occurred loading the data")
} else {
var saveError : NSError? = nil
if !managedObjectContext!.save(&saveError) {
println("Could not update record")
} else {
tableView.reloadData()
}
}
}
tableView.reloadData()
}
SettingCell.swift
class SettingCell: UITableViewCell {
@IBOutlet weak var settingsLabel: UILabel!
@IBOutlet weak var settingsSwitch: UISwitch!
var cellDelegate: SettingCellDelegate?
@IBAction func handledSwitchChange(sender: UISwitch) {
self.cellDelegate?.didChangeSwitchState(sender: self, isOn:settingsSwitch.on)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
SettingItem.swift
class SettingItem: NSObject {
var settingName : String?
var switchState : Bool?
override init() {
super.init()
}
init (settingName: String?, switchState : Bool?) {
super.init()
self.settingName = settingName
self.switchState = switchState
}
}
SettingCellDelegate.swift
protocol SettingCellDelegate {
func didChangeSwitchState(# sender: SettingCell, isOn: Bool)
}
finally this is my output,
Upvotes: 3
Views: 3382
Reputation: 39978
You're not changing the value of the LogItem before saving. Please do it accordingly, also this code may generate compiler errors as I'm not well-versed in the swift language, I just write the pseudo code that may help you.
var fetchedResults = managedObjectContext!.executeFetchRequest(fetchRequest, error: &error) as? [LogItem]
if let setting = fetchedResults {
if error != nil {
println("An error occurred loading the data")
}
else {
//now you have array of LogItem in your case it's one (assuming that you have unique name
//change the item's switch state and then save it
//Please make a count check here before getting the object
/*
if count == 0 -->> record doesn't exist
else -->> record exist
*/
var settingLogItem = setting[0]
settingLogItem.switchState = isOn
var saveError : NSError? = nil
if !managedObjectContext!.save(&saveError) {
println("Could not update record")
}
else {
tableView.reloadData()
}
}
}
Upvotes: 2