Amateur User
Amateur User

Reputation: 91

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

Upvotes: 0

Views: 518

Answers (2)

Tuslareb
Tuslareb

Reputation: 1200

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"

    }
}

Upvotes: 2

Wain
Wain

Reputation: 119041

You either need to pass the details view controller

  1. A list of all managed objects and an index for where in the list to start
  2. A current managed object and a callback to get the next object

In order for it to have enough information to do what you want. The callback approach is nicest and is a simple form of delegate, where your master view controller is the delegate supplying the extra data.

Upvotes: 1

Related Questions