jeudi 3 mars 2016

Core Data One to many relation not storing its data

I have a Table view based app that has a MasterTableViewController and a DetailChildTableViewController.

MasterTableViewController has a + in the Nav bar so a user is presented with a view to enter a name for that Folder in a textfield. Once the user is done, the clock done and this folder is then stored using Core Data and displays this new folder in the MasterTableViewController.

Here is the code for this specific TableViewController

MasterTableViewController

   class MasterTableViewController: UITableViewController, NSFetchedResultsControllerDelegate {


let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var fetchedResultsController : NSFetchedResultsController = NSFetchedResultsController()

// Populate fetched results controller
func getFetchedResultController() -> NSFetchedResultsController {

    fetchedResultsController = NSFetchedResultsController(fetchRequest: taskFetchRequest(), managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)

    return fetchedResultsController

}


func taskFetchRequest() -> NSFetchRequest {

    let fetchRequest = NSFetchRequest(entityName: "Folder")
    let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)


    fetchRequest.sortDescriptors = [sortDescriptor]
    return fetchRequest
}


}
override viewDidLoad(){
fetchedResultsController = getFetchedResultController()
    fetchedResultsController.delegate = self
    do {
        try fetchedResultsController.performFetch()
    } catch _ {
    }
 }

 // Table View Methods to show data in Custom UITableViewCell and Segue method....

The rest of the code in this controller just has methods to display the data in the table view cell and a segue method that passes the Core Data name to the next view controller as the user taps the newly created cell object.

Here is the Code to Create this specific Object to save and display on MasterTableViewController

AddViewController

class addItemTableViewController: UITableViewController {

@IBOutlet weak var FolderName: UITextField!

// Use the same managed object to save

let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext

 @IBAction func Done(sender: AnyObject){

 // Calling a function to save the folder to core data
 saveFolder()
 self.dismissViewControllerAnimated(true, completion: nil)
 }

// Function that saves

func saveFolder(){
 let entityDescription = NSEntityDescription.entityForName("Folder", inManagedObjectContext: managedObjectContext)
    let item = Folder(entity: entityDescription!, insertIntoManagedObjectContext: managedObjectContext)

    item.name = FolderName.text!


    // Passed Value of the color picker table view below


    do {
        try managedObjectContext.save()
        print("Successfully Saved \n")
    } catch _ {
    }
}

}

So this code basically saves the newly entered Folder and dismisses the folder name view and the MasterTableViewController shows this new folder.

The problem lies in the DetailChildTableViewController where it is the detail of each Folder created in MasterTableViewController.

Here is the code for the final tableview Controller

** DetailChildTableViewController**

   class DetailChildTableViewController: UITableViewController, UIPopoverPresentationControllerDelegate, NSFetchedResultsControllerDelegate {

let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext

var fetchedResultsController : NSFetchedResultsController = NSFetchedResultsController()

// Populate fetched results controller
func getFetchedResultController() -> NSFetchedResultsController {

    fetchedResultsController = NSFetchedResultsController(fetchRequest: taskFetchRequest(), managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)

    return fetchedResultsController

}


func taskFetchRequest() -> NSFetchRequest {

    let fetchRequest = NSFetchRequest(entityName: "List")
    let sortDescriptor = NSSortDescriptor(key: "itemListName", ascending: false)


    fetchRequest.sortDescriptors = [sortDescriptor]
    return fetchRequest
}

 override func viewDidLoad() {
    super.viewDidLoad(){

    // Core data
    fetchedResultsController = getFetchedResultController()
    fetchedResultsController.delegate = self
    do {
        try fetchedResultsController.performFetch()
    } catch _ {
    }

    self.tableView.reloadData()

}

 // MARK: - Display the results in table view

 override func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    if let sections = fetchedResultsController.sections {
        return sections.count
    }

    return 0
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    if let sections = fetchedResultsController.sections {
        let currentSection = sections[section]
        return currentSection.numberOfObjects
    }

    return 0
}

}

This DetailChildTableViewController also has a + button in the navigation bar and brings up a similar AddViewController to add data to this specific folder with the same Core Data methods.

The problem is that when i create 2 entities in my MasterTableViewController, say for example:

  • Folder_One
  • Folder_Two

and i go into Folder_Two and create a list object in this folder and then go back to the MasterTableViewController and then select Folder_One, It still shows that same list object which i created in Folder_Two.

How can i approach a solution to this simple yet unclear problem?

Here is my Data model by the way:

TestApp.xcdatamodel

Entities:

  1. Folder
  2. List

    Atributes: name of type String (for Folder entity) itemListName of type String (for List entity)

    Relationships: (for Folder entity) relation destination: List

Note that List entity is not listed as having a relationship to Folder. I set Folder to have relationship to List as a One to many relation.

What did i do wrong and how can i approach this?

Aucun commentaire:

Enregistrer un commentaire