I have been searching for days on how to work with one to many relationships. But I can't get it figured out.
I am working on a app which stores the grades of a subject. So one subject has a to-many relationship with grades. All the data is currently stored in a array.
var vakken: [(naam:String, voorkeurGemiddelde:Double, wegingGemiddelde:Double, cijfer:[Double], weging:[Double], gemiddelde:Double)] = []
Where the the [Double]'s - Cijfer and weging- are attributes of a grade.
I currently have the following for saving the data:
let context = AppDelegate().managedObjectContext
// Create subject
let entitySubject = NSEntityDescription.entityForName("Subject", inManagedObjectContext: context)
let Subject = NSManagedObject(entity: entitySubject!, insertIntoManagedObjectContext: context)
// Populate subject
Subject.setValue(vakken.last!.naam, forKey: "name")
Subject.setValue(vakken.last!.voorkeurGemiddelde, forKey: "voorkeurGemiddelde")
Subject.setValue(vakken.last!.wegingGemiddelde, forKey: "wegingNP")
Subject.setValue(vakken.last!.gemiddelde, forKey: "gemiddelde")
for var j = 0; j < vakken.last!.cijfer.count-1; j++ {
let Grade = NSEntityDescription.insertNewObjectForEntityForName("Grade", inManagedObjectContext: context)
Grade.setValue(vakken.last!.cijfer[j], forKey: "cijfer")
Grade.setValue(vakken.last!.weging[j], forKey: "weging")
Subject.setValue(NSSet(object: Grade), forKey: "grade")
}
do{
try context.save()
}catch{
print("error")
}
I am using the data in a tableView.
I have seen in some tutorials that the use: var vakken = [NSManagedObject]()
and then use it in a tableview.
1. But is this also possible with the model I have, and should I use it?
I first thought was to just save the data when the app terminates, so I would have the code in the app delegate, and then just retrive it when the app starts.
2. But how would I get the array to the appdelegate and would this be smart?
And for fetching the data I have this:
let fetchRequest = NSFetchRequest(entityName: "Subject")
// // Add Sort Descriptor
// let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
// fetchRequest.sortDescriptors = [sortDescriptor]
let context = Appdelegate().managedObjectContext
// Execute Fetch Request
do {
let result = try context.executeFetchRequest(fetchRequest)
print(result)
} catch {
let fetchError = error as NSError
print(fetchError)
}
3. But how would I get from the result my array back or if I use NSManagedObject how can I refer to the attributes and in most particular the grades.
I also sort my array by name which can be A-Z or Z-A, and I sort by average which can be 10-1 or 1-10. I have the code to sort it in my array.
4. But I don't know how to sort this with core data.
I have also seen a tutorial where they made a class for the attributes link. So I made one my self:
import UIKit
import CoreData
import Foundation
class Subject: NSManagedObject {
@NSManaged var gemiddelde: Double
@NSManaged var name: String
@NSManaged var voorkeurGemiddelde: Double
@NSManaged var wegingNP: Double
@NSManaged var Grades: NSSet
}
class Grade: NSManagedObject {
@NSManaged var cijfer: Double
@NSManaged var weging: Double
@NSManaged var subject: Subject
}
extension Subject {
func addTagObject(value:Grade) {
let items = self.mutableSetValueForKey("grade");
items.addObject(value)
}
func removeTagObject(value:Grade) {
let items = self.mutableSetValueForKey("grade");
items.removeObject(value)
}
}
5. But I don't know if I need it nor how to use it?
If you have any advise, tips, know good tutorials or know one of these questions. Your help would be appreciated.
If you need any more information just let me know. :)
Update:
I have this code to get the object of the subject witch is clicked.
if let indexPath = self.tableView.indexPathForSelectedRow {
let object = self.fetchedResultsController.objectAtIndexPath(indexPath)
let controller = segue.destinationViewController as! VakTableViewController
controller.vak = object as! Subject
}
And this is the code on the receiving end:
var vak: Subject! {
didSet {
// Update the view.
cijfers = vak.valueForKeyPath("grades.cijfer")!.allObjects as! [Double]
wegingen = vak.valueForKeyPath("grades.weging")!.allObjects as! [Double]
self.tableView.reloadData()
}
}
var cijfers: Array<Double>!
var wegingen: Array<Double>!
6. But how can i delete on of the grades?
I have tried this:
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
if cijfers.count != 1 {
let entityGrade = NSEntityDescription.entityForName("Grade", inManagedObjectContext: mangedobjectcontext)
let grade = Grade(entity: entityGrade!, insertIntoManagedObjectContext: mangedobjectcontext)
grade.cijfer = cijfers[indexPath.row]
grade.weging = wegingen[indexPath.row]
vak.removeGradeObject(grade)
do{
try mangedobjectcontext.save()
}catch{
print("error")
}
cijfers.removeAtIndex(indexPath.row)
wegingen.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
print(vak.valueForKeyPath("grades.cijfer")?.allObjects)
}
}
}
But this doesn't work.
7. And how can i save the vak(subject) to the context when i just change own of the variable?
like this: vak.gemiddelde = newgemiddelde