Search code examples
swiftuitableviewcore-datansfetchedresultscontroller

How to update user interface on Core Data?


I have an app with UITableView, Core Data and NSFetchedResultsController as well. I have passed data to the DetailViewController. And I can delete them from the DetailViewController! In the Apple's iOS Notes app, you can see such as functions as I wanted! When you delete a notes from the DetailViewController ( for example ), object deleted and Notes app automaticlly shows the next or previos notes! I want to create such as function. How update user interface after deleted current object? Here's my codes! Thanks ` import UIKit import CoreData

class DetailViewController: UIViewController {

@IBOutlet weak var containerLabel: UILabel!

var retrieveData:NSManagedObject!
var managedObjectContext:NSManagedObjectContext!
var manager:Manager!

override func viewDidLoad() {
    super.viewDidLoad()
// Do any additional setup after loading the view.

    self.containerLabel.userInteractionEnabled = false
    self.containerLabel.textColor = UIColor.redColor()
    self.containerLabel.alpha = 0

    UIView.animateWithDuration(2.5) { () -> Void in
        self.containerLabel.alpha = 1
    }


    if let demo = self.retrieveData.valueForKey("titleField") as? String {
     self.containerLabel.text = demo
    }

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

@IBAction func backToMain(sender: AnyObject) {
    // Back to the MainTableViewController
    self.dismissViewControllerAnimated(true, completion: nil)
}
@IBAction func trashButton(sender: AnyObject) {

    self.managedObjectContext.deleteObject(retrieveData)

    do {
    try self.managedObjectContext.save()
    } catch {

    }
    self.dismissViewControllerAnimated(true, completion: nil)


}

`

If I have 5 items on the list like so:

enter image description here

When I select fourth item from the list ( for example ). And detailVC shows me selected item like this:

enter image description here

And I want to delete them. When I delete "Four" and then my containerLabel.text shows previous objects from the list. They're after "Four" is deleted, "Three","Two" and "One" as well. After "One" is deleted my containerLabel.text shows strings

enter image description here

But I have left single object called as "Five"

enter image description here

My problem is "Five"! I can't delete it. Example: In iOS Notes App, if you have five objects on the list like my demo app. When you select fourth object from the list ( for example ). And begin deleting them, after "Four" is delete iOS Notes App shows "Five". And "Five" ( last object on the list ) is deleted and then iOS Notes App shows "Three", "Two" and "One". Maybe problem line is here:

if index != 0 { self.retrieveData = fetchedObject[index! - 1] } else { self.retrieveData == fetchedObject[0] }

enter image description here


Solution

  • Let's take the easy (but not so elegant) route here. You'll have to pass over all the fetched objects to the detail VC like this:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    
    if segue.identifier == "yourSegueIdentifier"{
    
        if let destinationVC = segue.destinationViewController as? DetailViewController{
    
            destinationVC.managedObjectContext = yourContext
            destinationVC.retrieveData = yourManagedObject
            destinationVC.arrayOfFetchedObjects = yourFetchedResultsController.fetchedObjects
            //pass over other data...
    
            }
        }
    }
    

    Then, in your detailVC, write a method that will be executed when you press the delete button. Something like this:

    @IBAction func trashButton(sender: AnyObject) {
    
    //make sure you have an array with YourObjects
    guard let fetchedObjects = arrayOfFetchedObjects as? [YourObjectType] else {return}
    
    //get index of the shown object in the array of fetched objects
    let indexOfObject = fetchedObjects.indexOf(retrieveData)
    
    //delete the object from the context
    self.managedObjectContext.deleteObject(retrieveData)
    
    do {
        try self.managedObjectContext.save()
    
        //delete the object from the fetchedObjects array
        fetchedObjects.removeAtIndex(indexOfObject)
    } catch {
    
    }
    
    //get the object that should be shown after the delete
    if indexOfObject != 0{
        //we want the object that represents the 'older' note
        retrieveData = fetchedObjects[indexOfObject - 1]
        updateUserInterface(true)
    
    }
    else{
        //the index was 0, so the deleted object was the oldest. The object that is the oldest after the delete now takes index 0, so just use this index. Also check for an empty array.
    
        if fetchedObjects.isEmpty{ 
             updateUserInterface(false)
         }
        else{
            retrieveData = fetchedObjects[0]
            updateUserInterface(true)
        }
    
        }
    }
    
    
    func updateUserInterface(note: Bool){
    
    switch note{
    
        case true:
    
            //update the user interface
            if let demo = retrieveData.valueForKey("titleField") as? String {
                self.containerLabel.text = demo
            }
    
        case false:
    
            self.containerLabel.text = "no more notes"
    
        }
    }