How to overwrite Core Data attribute in Swift - ios

I'm trying to update an attribute in Core Data and then display it. However, when I tell the program to display it, it displays the original value.
Based off the code below, username is set to a String. I know 100% that username is saved into Core Data. However, when I try to update it, it saves to Core Data, but prints out the old value. How can I print out only the "newest" value?
import UIKit
import CoreData
class NameSettings: UIViewController {
#IBOutlet var nameText: UITextField!
var userID: String!
var username: String!
override func viewDidLoad() {
super.viewDidLoad()
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext!
var request = NSFetchRequest(entityName: "Users")
request.returnsObjectsAsFaults = false
var results: NSArray = context.executeFetchRequest(request, error: nil)!
var res = results [0] as NSManagedObject
userID = res.valueForKey("userID") as String
username = res.valueForKey("username") as String
println(username)
nameText.text = username
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func saveTapped(sender: AnyObject) {
//println(userID)
var query = PFQuery(className:"_User")
query.getObjectInBackgroundWithId(userID) {
(update1: PFObject!, error: NSError!) -> Void in
if error == nil {
update1["username"] = self.nameText.text
update1.saveEventually()
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext!
var updateUser = NSEntityDescription.insertNewObjectForEntityForName("Users", inManagedObjectContext: context) as NSManagedObject
updateUser.setValue(self.nameText.text, forKey: "username")
context.save(nil)
//println(self.nameText.text)
self.navigationController?.popToRootViewControllerAnimated(true)
}
}
}
}
NOTE: All the println's are just for debugging.

As your code stands now, you're not overwriting any NSManagedObject; you're inserting a new one, i.e. insertNewObjectForEntityForName.
Instead, what you can do is declare the NSManagedObject you want to save and the NSManagedObjectContext you want to save to as global variables; then simply set a new value for the NSManagedObject's relevant key before saving to the NSManagedObjectContext, ex:
var userID: String!
var username: String!
var res : NSManagedObject!
var context : NSManagedObjectContext!
override func viewDidLoad() {
super.viewDidLoad()
//...
context = appDel.managedObjectContext! // <-- Use global var
var request = NSFetchRequest(entityName: "Users")
request.returnsObjectsAsFaults = false
var results: NSArray = context.executeFetchRequest(request, error: nil)!
res = results [0] as NSManagedObject // <-- Use global var
//...
}
#IBAction func saveTapped(sender: AnyObject) {
//println(userID)
var query = PFQuery(className:"_User")
query.getObjectInBackgroundWithId(userID) {
(update1: PFObject!, error: NSError!) -> Void in
if error == nil {
update1["username"] = self.nameText.text
update1.saveEventually()
res.setValue(self.nameText.text, forKey: "username")
context.save(nil)
//println(self.nameText.text)
self.navigationController?.popToRootViewControllerAnimated(true)
}
}
}

Related

MBProgressHUD causing iOS application to crash (Swift 2.0)

I have a ViewController which saves user inputs to CoreData and after the save is attempted displaying MBProgressHUD to state if the save was successful or not.
I have an AddNewViewController class
class AddNewViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate {
#IBOutlet weak var inputErrorMessage: UILabel!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var amountLabel: UILabel!
#IBOutlet weak var dayPicker: UIPickerView!
#IBOutlet weak var durationPicker: UIPickerView!
#IBOutlet weak var nameTextField: UITextField!
#IBOutlet weak var amountTextField: UITextField!
#IBOutlet weak var notesTextField: UITextField!
//variable to contrain the origin view controller
var originVC: String?
// variables to hold user input
var name: String?
var amount: Double?
var notes: String?
var durationDay: Double?
var durationType: String?
// The days and duration options to display in the pickers
var durationPickerDataSource = ["Day(s)","Week(s)","Month(s)","Year(s)"];
var dayPickerDataSource = ["1","2","3","4","5","6","7","8","9","10","11","12"];
#IBAction func saveButton(sender: AnyObject) {
CoreDataStatic.data.saveIncomeBudgetAndExpenses(originVC!, name: name!, amount: amount, durationDay: durationDay!, durationType: durationType!, notes: notes!)
}
/**
The number of columns in the picker view.
*/
func numberOfComponentsInPickerView(dayPickerView: UIPickerView) -> Int {
return 1
}
/**
The number of items in the picker view. Equal to the number of days(12) and duration options(4) .
*/
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == durationPicker {
return durationPickerDataSource.count;
}
else {
return dayPickerDataSource.count;
}
}
/**
Gets the titles to use for each element of the picker view.
*/
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == durationPicker{
durationType = durationPickerDataSource[row]
return durationType
}
else {
durationDay = Double(dayPickerDataSource[row])
return dayPickerDataSource[row]
}
}
/**
Display acknowledgement if the Income, Budget or Fixed Expense saved.
*/
func displayMessage(origin: String) {
var message : String
//Changes the message depending on what the user was trying to save.
if CoreDataStatic.data.saved == true {
message = "\(origin) saved!"
}
else if CoreDataStatic.data.saved == false {
message = "Error: \(origin) failed to save!"
}
else {
message = "Error!"
}
print(message)
//displays acknowledgement for 2 seconds.
/*let acknowledgement = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
acknowledgement.mode = MBProgressHUDMode.Text
acknowledgement.label.text = message
acknowledgement.hideAnimated(true, afterDelay: 2)*/
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.durationPicker.dataSource = self;
self.durationPicker.delegate = self;
self.dayPicker.dataSource = self;
self.dayPicker.delegate = self;
}
A CoreData class:
struct CoreDataStatic {
static let data = CoreData()
}
public class CoreData {
var appDel : AppDelegate
//Manage a collection of managed objects.
let context : NSManagedObjectContext
//Describes an entity in Core Data.
let incomeEntity : NSEntityDescription
let budgetEntity : NSEntityDescription
let fixedExpenseEntity : NSEntityDescription
//Retrieve data from Core Data with the entity 'Scores'.
let income = NSFetchRequest(entityName: "Income")
let budget = NSFetchRequest(entityName: "Budget")
let fixedExpense = NSFetchRequest(entityName: "FixedExpenses")
//Set the key that needs updating which is always 'score'
let nameKeyToUpdate = "name"
let amountDayKeyToUpdate = "amountDay"
let amountWeekKeyToUpdate = "amountWeek"
let amountMonthKeyToUpdate = "amountMonth"
let amountYearKeyToUpdate = "amountYear"
let durationDayKeyToUpdate = "durationDay"
let durationTypeKeyToUpdate = "durationType"
let notesKeyToUpdate = "notes"
var saved : Bool?
func saveIncomeBudgetAndExpenses(origin: String, name: String, amountDay: Double, amountWeek: Double, amountMonth: Double, amountYear: Double, durationDay: Double, durationType: String, notes: String) {
//saving in enity depending on origin view controller
let entity : NSEntityDescription
if origin == "Income" {
entity = NSEntityDescription.entityForName("Income", inManagedObjectContext: context)!
}
else if origin == "Budget" {
entity = NSEntityDescription.entityForName("Budget", inManagedObjectContext: context)!
}
else {
entity = NSEntityDescription.entityForName("FixedExpenses", inManagedObjectContext: context)!
}
let saveNew = NSManagedObject(entity: entity,
insertIntoManagedObjectContext:context)
// add user input to the relevant entity
saveNew.setValue(name, forKey: nameKeyToUpdate)
saveNew.setValue(amountDay, forKey: amountDayKeyToUpdate)
saveNew.setValue(amountWeek, forKey: amountWeekKeyToUpdate)
saveNew.setValue(amountMonth, forKey: amountMonthKeyToUpdate)
saveNew.setValue(amountYear, forKey: amountYearKeyToUpdate)
saveNew.setValue(durationDay, forKey: durationDayKeyToUpdate)
saveNew.setValue(durationType, forKey: durationTypeKeyToUpdate)
saveNew.setValue(notes, forKey: notesKeyToUpdate)
do {
try context.save()
print("saved")
saved = true
}
catch _ {
print("didnt save")
saved = false
}
AddNewViewController().displayMessage(origin)
}
init(){
appDel = (UIApplication.sharedApplication().delegate as! AppDelegate)
context = appDel.managedObjectContext
incomeEntity = NSEntityDescription.entityForName("Income", inManagedObjectContext: context)!
budgetEntity = NSEntityDescription.entityForName("Budget", inManagedObjectContext: context)!
fixedExpenseEntity = NSEntityDescription.entityForName("FixedExpenses", inManagedObjectContext: context)!
}
}
This code runs and as expected however when the commented out section in the displayMessage() function is uncommented I get the following error:
"fatal error: unexpectedly found nil while unwrapping an Optional value"
due to the line self.durationPicker.dataSource = self; in the override viewDidLoad()
Any help would be appreciated.
Note* if i call the displayMessage() within the saveButton function the code works so unsure why it isn't working when calling the message from the CoreData class.
I am unsure if this is the correct way about it but i found a fix.
a variable (bool) was created called attemptSave which is defaulted to false.
within the saveIncomeBudgetAndExpenses try and catch, the attemptSave is changed to true.
The displayMessage() function is now called within both button clicks using an if statement to check if an attemptSave is yes, if so, call function.

why can we use a NSManagedObjectContext without setting its persistentStoreCoordinator in CoreData

the normal initialize of a context is like this:
lazy var context : NSManagedObjectContext = {
let context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
context.persistentStoreCoordinator = self.coordinator
return context
}()
but why i can initialized the context in this way:
var managedObjectContext : NSManagedObjectContext?
lazy var note: Note? = {
if let context = self.managedObjectContext {
return NSEntityDescription.insertNewObjectForEntityForName("Note", inManagedObjectContext: context) as? Note
}
return .None
}()
if i don't set the persistentStoreCoordinator,which way will the context store the entity.by the way,this is not the first context created in the demo,it is just the context for a manageredobject named Node
waiting online ..........
the whole code is :
import UIKit
import CoreData
class CreateNoteViewController : UIViewController, UITextFieldDelegate, UITextViewDelegate {
var managedObjectContext : NSManagedObjectContext?
lazy var note: Note? = {
if let context = self.managedObjectContext {
return NSEntityDescription.insertNewObjectForEntityForName("Note", inManagedObjectContext: context) as? Note
}
return .None
}()
#IBOutlet var titleField : UITextField!
#IBOutlet var bodyField : UITextView!
#IBOutlet var attachPhotoButton : UIButton!
#IBOutlet var attachedPhoto : UIImageView!
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if let image = note?.image {
attachedPhoto.image = image
view.endEditing(true)
} else {
titleField.becomeFirstResponder()
}
}
#IBAction func saveNote() {
note?.title = titleField.text
note?.body = bodyField.text
if let managedObjectContext = managedObjectContext {
do {
try managedObjectContext.save()
}
catch let error as NSError {
print("Error saving \(error)", terminator: "")
}
}
performSegueWithIdentifier("unwindToNotesList", sender: self)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
saveNote()
textField.resignFirstResponder()
return false
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "AttachPhoto" {
if let nextViewController = segue.destinationViewController as? AttachPhotoViewController {
nextViewController.note = note
}
}
}
}
the function of the viewcontroller is to pick a photo from the local alarm,and save the title, the Node is used to save all the information,so the author did use the default context(even i don't know why he don't use the default context),he initialize a new context to save the node ,even not set anything ,its amazing ,even the path of file path he haven't set,
i will show you the default of stack:
import Foundation
import CoreData
class CoreDataStack: CustomStringConvertible {
var modelName : String
var storeName : String
var options : [String : AnyObject]?
init(modelName:String, storeName:String, options: [String : AnyObject]? = nil) {
self.modelName = modelName
self.storeName = storeName
self.options = options
}
var description : String {
return "context: \(context)\n" +
"modelName: \(modelName)" +
"storeURL: \(storeURL)\n"
}
var modelURL : NSURL {
return NSBundle.mainBundle().URLForResource(self.modelName, withExtension: "momd")!
}
var storeURL : NSURL {
var storePaths = NSSearchPathForDirectoriesInDomains(.ApplicationSupportDirectory, .UserDomainMask, true) as [String]
let storePath = String(storePaths[0]) as NSString
let fileManager = NSFileManager.defaultManager()
do {
try fileManager.createDirectoryAtPath(storePath as String, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
print("Error creating storePath \(storePath): \(error)")
}
let sqliteFilePath = storePath.stringByAppendingPathComponent(storeName + ".sqlite")
return NSURL(fileURLWithPath: sqliteFilePath)
}
lazy var model : NSManagedObjectModel = NSManagedObjectModel(contentsOfURL: self.modelURL)!
var store : NSPersistentStore?
lazy var coordinator : NSPersistentStoreCoordinator = {
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.model)
do {
self.store = try coordinator.addPersistentStoreWithType(
NSSQLiteStoreType,
configuration: nil,
URL: self.storeURL,
options: self.options)
} catch var error as NSError {
print("Store Error: \(error)")
self.store = nil
} catch {
fatalError()
}
return coordinator
}()
lazy var context : NSManagedObjectContext = {
let context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
context.persistentStoreCoordinator = self.coordinator
return context
}()
}
Your first code snippet creates a managed object context:
lazy var context : NSManagedObjectContext = {
let context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
context.persistentStoreCoordinator = self.coordinator
return context
}()
Your second code snippet does not create a managed object context:
var managedObjectContext : NSManagedObjectContext?
lazy var note: Note? = {
if let context = self.managedObjectContext {
return NSEntityDescription.insertNewObjectForEntityForName("Note", inManagedObjectContext: context) as? Note
}
return .None
}()
The second snippet is using Swift optional unwrapping to check that self.managedObjectContext is not nil. If it isn't nil, it assigns it to a local variable context. You don't set the persistent store coordinator here because you are not creating the managed object context. This code assumes that self.managedObjectContext was already created somewhere else (probably in the first snippet).
A managed object context isn't much use without a persistent store coordinator, and you can't do anything useful with it. You especially can't save data with it. But since your second code snippet isn't creating a managed object context, that doesn't matter here.
There are a couple of possible reasons why the coordinator is not a param to the init method.
Since a context can either work with a store coordinator or a parent context, init methods for each of these cases that also include the concurrency type param would be messy and make subclassing more tricky. So they instead opted to have a set once property, i.e. if you set them again it exceptions with an inconsistency "Context already has a coordinator; cannot replace.".
Allowing a context to be created before it is ready to be used gives more flexibility to the initialisation routine of the app. First gives flexibility in how each part of the stack is created, model, coordinator, context, etc. And second, the context can be passed to view controllers first, and then the store loaded and coordinator set on the context afterwards. And the viewController can listen for NSPersistentStoreCoordinatorStoresDidChangeNotification and then check if the context now has a valid coordinator and then perform its view updates.

CoreData - Crashing while saving

So, this is my code:
ViewController 1 :
class ViewSet: UIViewController {
#IBOutlet var Label_1: UILabel!
#IBOutlet var Label_2: UILabel!
#IBOutlet var Text: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var moc: NSManagedObjectContext = appDel.managedObjectContext!
var request = NSFetchRequest(entityName: "TestingCoreData")
request.returnsObjectsAsFaults = false;
var results: NSArray = moc.executeFetchRequest(request, error: nil)!
if (results.count > 0) {
var res = results[0] as! NSManagedObject
Label_1.text = res.valueForKey("label_1") as? String
Label_2.text = res.valueForKey("label_2") as? String
Text.text = res.valueForKey("text") as? String
} else {
println("No results found")
}
}
}
ViewController 2:
import UIKit
import CoreData
class Label_1: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBOutlet var Label_1: UITextField!
#IBAction func addLabel_1(sender: AnyObject) {
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var moc: NSManagedObjectContext = appDel.managedObjectContext!
var label1 = NSEntityDescription.insertNewObjectForEntityForName("TestingCoreData", inManagedObjectContext: moc) as! NSManagedObjectContext
label1.setValue("\(Label_1.text)", forKey: "label_1")
moc.save(nil)
println("Object saved")
performSegueWithIdentifier("toLabel2", sender: self)
}
}
ViewController 3:
import UIKit
import CoreData
class Label_2: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBOutlet var Label_2: UITextField!
#IBAction func add(sender: AnyObject) {
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var moc: NSManagedObjectContext = appDel.managedObjectContext!
var label2 = NSEntityDescription.insertNewObjectForEntityForName("TestingCoreData", inManagedObjectContext: moc) as! NSManagedObjectContext
label2.setValue("\(Label_2.text)", forKey: "label_2")
moc.save(nil)
println("Object saved")
performSegueWithIdentifier("toText", sender: self)
}
}
ViewController 4:
import UIKit
import CoreData
class Text: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBOutlet var Text: UITextView!
#IBAction func done(sender: AnyObject) {
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var moc: NSManagedObjectContext = appDel.managedObjectContext!
var text = NSEntityDescription.insertNewObjectForEntityForName("TestingCoreData", inManagedObjectContext: moc) as! NSManagedObjectContext
text.setValue("\(Text.text)", forKey: "text")
moc.save(nil)
println("Object saved")
navigationController?.popToRootViewControllerAnimated(true)
}
}
I believe the code is very simple. I'm trying to learn my way through CoreData, but I can't seem to properly make it work.
It crashes here, when I press add to go to the 3rd view controller:
Can anyone help me? I'm new to this stuff! Thanks in advance

How to delete several different data from Core Data in Swift?

I have Core Data with five objects. It's four String and one NSData (UIImage). I save them in Core Data. Then load in UIViewController and I want to delete them from Core Data and I got different errors. I tried different methods but it doesn't helped me. How do I delete these data?
var name: String!
var text: String!
var image: UIImage!
var url: String!
var data: String!
func deleteAll() {
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var managedObjectContext: NSManagedObjectContext = appDel.managedObjectContext!
var coreDataName: NSManagedObject = (name as AnyObject?) as! NSManagedObject
var coreDataImage: NSManagedObject = (image as AnyObject?) as! NSManagedObject
var coreDataText: NSManagedObject = (text as AnyObject?) as! NSManagedObject
var coreDataData: NSManagedObject = (data as AnyObject?) as! NSManagedObject
var coreDataURL: NSManagedObject = (url as AnyObject?) as! NSManagedObject
managedObjectContext.deleteObject(coreDataName)
managedObjectContext.deleteObject(coreDataImage)
managedObjectContext.deleteObject(coreDataText)
managedObjectContext.deleteObject(coreDataData)
managedObjectContext.deleteObject(coreDataURL)
managedObjectContext.save(nil)
buttonDelete.enabled = false
buttonShare.enabled = false
}
}
My Core Data file
import Foundation
import CoreData
#objc(News)
class News: NSManagedObject {
#NSManaged var dateNewsCoreDataString: String
#NSManaged var imageNewsCoreData: NSData // NSData
#NSManaged var nameNewsCoreData: String
#NSManaged var textNewsCoreData: String
#NSManaged var urlNewsCoreData: String
}
I changed my code and it work for me.
var detailObject: AnyObject? // It's data from FavoriteTableViewController
func deleteAll() {
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var managedObjectContext: NSManagedObjectContext = appDel.managedObjectContext!
var dataDelete = detailObject as! NSManagedObject
managedObjectContext.deleteObject(dataDelete)
managedObjectContext.save(nil)
managedObjectContext.save(nil)
buttonDelete.enabled = false
buttonShare.enabled = false
}

How do I update an existing record in Core Data?

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

Resources