-2

I'd like to update an object in Core Data. This is my code:

var detailTaskModel: TaskModel!
detailTaskModel.date = dateFromDP         //update value

let appDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
appDelegate.saveContext()

I'm using a NSFetchedResultsController and Swift.

Update:

var fetchedResultsController: NSFetchedResultsController = NSFetchedResultsController()

My func for loading the CoreData data:

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

    var cell: TaskCell = tableView.dequeueReusableCellWithIdentifier("myCell") as TaskCell

    let thisTask = fetchedResultsController.objectAtIndexPath(indexPath) as TaskModel
    cell.textLabel?.text = thisTask.task
    return cell
}

Saving CoreData:

let appDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
let entityDescription = NSEntityDescription.entityForName("TaskModel", inManagedObjectContext: managedObjectContext!)
let task = TaskModel(entity: entityDescription!, insertIntoManagedObjectContext: managedObjectContext!)
task.task = labelText
pablo
  • 61
  • 1
  • 1
  • 6

3 Answers3

7

You simply update any property of Core data object and call save on NSManagedObjectContext. You can also check for any changes with hasChanges method.

 managedObject.setValue("newValue", forKey: "propertyName") 

Update your object like above or direct call assignment and do the following

if let moc = self.managedObjectContext {
   var error: NSError? = nil
   if moc.hasChanges {
       !moc.save(&error)
   }
}
Abubakr Dar
  • 4,078
  • 4
  • 22
  • 28
  • Make sure that your object and save method are under the same NSManagedObjectContext – Abubakr Dar Feb 15 '15 at 14:39
  • I've done it on this way. Is this correct: `let thisTask = fetchedResultsController.objectAtIndexPath(editIndexPath) as TaskModel thisTask.date = dateFromDP // dateFromDP = the new date self.fetchedResultsController.managedObjectContext.save(nil)` ? – pablo Feb 18 '15 at 14:46
  • @pablo The code should work. Can you pass in the NSError object in save and check what the issue is; then I'll be able to help you more. – Abubakr Dar Feb 20 '15 at 06:53
  • Ok. If I run this code, the app crashes a the next launch at this line of code: `cell.textLabel?.text = thisTask.task` task is a label which should be load in a tableViewCell. – pablo Feb 20 '15 at 14:22
  • Well thats probably because thisTask.task is nil, print the value of thisTask.task to make sure its not nil – Abubakr Dar Feb 20 '15 at 15:57
  • Yes, thisTask.task is nil after running the code above. But why and how can I solve it? – pablo Feb 20 '15 at 16:33
  • You need to check when and where you initilize thisTask.task; Maybe it doesnt have proper value. There are two possibilities 1. thisTask might be nil 2. only thisTask.task is nil – Abubakr Dar Feb 20 '15 at 16:48
  • I don't know what I've done wrong. I updated my question with the function which loads the data. Hope it helps. P.S If I write `thisTask.task = "Some text"` before loading the data the app is not crashing. So just `thisTask.task`is nil. – pablo Feb 20 '15 at 18:36
  • @pablo Its not a big issue really, You just need to check where you assign value to thisTask. If you could share the assignment I could help you better – Abubakr Dar Feb 20 '15 at 18:39
  • I updated my question again. Are these the informations you need? – pablo Feb 20 '15 at 22:14
  • Are these informations useful? – pablo Feb 21 '15 at 12:39
  • Yes, You are making and assigning a new NSManagedObject, thats why its properties will always be nil by default. – Abubakr Dar Feb 21 '15 at 13:33
  • Thank you for your help! But how should I save the text in CoreData for not getting a crash? – pablo Feb 21 '15 at 18:51
  • well you can use if let value = labelText { task.task = value } – Abubakr Dar Feb 21 '15 at 19:15
  • Ok. It seems to work. But if I load the saved text it's not showing up. – pablo Feb 21 '15 at 20:56
  • This simply checks if the value is not nil then continue; so as long as value is nil that code wont work. You should set some value in task and then this code should work. – Abubakr Dar Feb 22 '15 at 07:27
  • Yes. The text is saved in CoreData. But I didn't get the text printed out. Is the code correct which loads the text which is saved in CoreData (task isn't nil)? – pablo Feb 23 '15 at 18:29
  • No, You need to use NSFetchRequest to get data from coredata. – Abubakr Dar Feb 23 '15 at 19:38
  • How could I do this? I tried so much but nothing is working. I give up soon. – pablo Feb 24 '15 at 16:56
4

Updating an object in CoreData is quite similar to creating a new one. First you have to fetch your object from CoreData using a fetchRequest. After that you can edit the fetched object and update it's attributes. After that, just save it back using the managedObjectContext.

Christian
  • 22,585
  • 9
  • 80
  • 106
  • I didn't get it working (still learning Swift). Could you post a few code snippets? – pablo Feb 15 '15 at 13:18
  • @pablo you may refer to this cheat sheet https://www.andrewcbancroft.com/2015/02/18/core-data-cheat-sheet-for-swift-ios-developers/#delete-single-entity – BabyPanda Oct 05 '16 at 07:54
1

You can do this, works for me.

if let container = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer{

        let context = container.viewContext

        let fetchRequest = NSFetchRequest<Account>(entityName: "Account")

        let name = self.txtAccount.text

        fetchRequest.predicate = NSPredicate(format: "name == %@", name!)

        do {

            let results = try context.fetch(fetchRequest)

            if (results.count > 0){

                for result in results{

                    id = result.id
                    number = result.number

                }

                actualNumber = (number + 1)

                //Update the account balance
                let update = results[0]
                update.number = actualNumber

                try context.save()

                return id

            }

        }catch let error {

            print("Error....: \(error)")

        }

You don't have to write 'result[0] as! NSManagedObject' because you have the NSFetchRequest of type Account and the constant "update" knows that.