我一直在寻找如何处理一对多关系的日子。但我无法弄清楚。
我正在开发一个存储学科成绩的应用程序。因此,一个科目与成绩之间存在多对多的关系。当前所有数据都存储在数组中。
var vakken: [(naam:String, voorkeurGemiddelde:Double, wegingGemiddelde:Double, cijfer:[Double], weging:[Double], gemiddelde:Double)] = []
其中[Double]-Cijfer和weging-是等级的属性。
我目前有以下保存数据的方法:
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")
}
我在tableView中使用数据。我在一些教程中看到了use : var vakken = [NSManagedObject]()
,然后在tableview中使用它。
1.但这对于我拥有的模型也是可行的,我应该使用它吗?
我首先想到的是只是在应用终止时保存数据,所以我会将代码保存在应用委托中,然后在应用启动时检索它。
2.但是我如何将阵列发送到appdelegate,这会很聪明吗?
对于获取数据,我有以下内容:
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.但是如何从数组的结果中得到结果,或者如果我使用NSManagedObject,如何引用属性,尤其是等级。
我还按名称对数组进行排序,可以是AZ或ZA,而按平均值可以是10-1或1-10。我有将其排序在数组中的代码。
4.但是我不知道如何用核心数据对它进行排序。
我还看过一个教程,在该教程中,他们为属性链接创建了一个类。所以我做了我自己:
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.但是我不知道我是否需要它,也不知道如何使用它?
如果您有任何建议,技巧,熟悉的教程或这些问题之一。您的帮助将不胜感激。
如果您需要更多信息,请告诉我。:)
更新:
我有此代码来获取主题巫婆被单击的对象。
if let indexPath = self.tableView.indexPathForSelectedRow {
let object = self.fetchedResultsController.objectAtIndexPath(indexPath)
let controller = segue.destinationViewController as! VakTableViewController
controller.vak = object as! Subject
}
这是接收端的代码:
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.但是我该如何删除年级?
我已经试过了:
// 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)
}
}
}
但这是行不通的。
7.当我只更改变量自己时,如何将vak(subject)保存到上下文中?
像这样:subject.middle = newgerm
要直接解决您的问题:
我在tableView中使用数据。我在一些教程中看到了use :
var vakken = [NSManagedObject]()
,然后在tableview中使用它。我拥有的模型也可以做到吗,我应该使用它吗
当然可以,但是使用可能会更好NSFetchedResultsController
(请参阅Apple Docs)。这是专门设计用来使用Core-Data中的数据轻松填充tableView的方法。
我首先想到的是只是在应用终止时保存数据,所以我会将代码保存在应用委托中,然后在应用启动时检索它。我如何将阵列发送到appdelegate,这会很聪明吗?
我不会在App委托中填充/保存数组。有人遵循Apple的模板项目,这些项目在App Delegate中构建CoreData堆栈。其他人有一个单独的类,可以实例化这些类来管理堆栈。从代码的外观来看,它目前使用前者。然后,您的视图控制器可以NSManagedObjectContext
使用以下方法从App Delegate获取:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context = appDelegate.managedObjectContext
(正如beyowulf指出的那样,您不应使用AppDelegate().managedObjectContext
它来创建新实例,而应引用现有实例)。一旦有了上下文,您的视图控制器就可以获取所需的数据,添加或更新现有记录等。
但是我如何从数组的结果中得到结果,或者如果我使用NSManagedObject,如何引用属性,尤其是等级。
result
是的数组NSManagedObjects
。您可以使用获得的属性值valueForKey
,“读”相当于setValue:(_, forKey:)
:
let firstObject = result[0]
let firstObjectName = firstObject.valueForKey("name")
同样,可以通过以下方式获得成绩:
let firstObjectGrades = firstObject.valueForKey("grades")
不过,还有更好的方法:请在下面查看您的最后一个问题。
我还按名称对数组进行排序,可以是AZ或ZA,而按平均值可以是10-1或1-10。我有将其排序在数组中的代码。但是我不知道如何用核心数据来排序。
提取数据时,对数据进行排序最容易。为此,NSSortDescriptor
请为抓取指定一个(请参阅Apple Docs):
let fetchRequest = NSFetchRequest(entityName: "Subject")
fetchRequest.sortDescriptors = [NSSortDescriptor(key:"name", ascending:true)
我还看过一个教程,其中他们为属性创建了一个类。我不知道是否需要它,也不知道如何使用它?
是的,使用它。这将使生活变得更加轻松。不用编写自己的类定义,而是在数据模型编辑器中使用Xcode菜单选项“ Create NSManagedObject subclasses”。它将为您创建类代码,还将设置每个实体使用相应的类。(如果您希望坚持使用自己的代码,则需要在数据模型编辑器中为每个实体修改“类”)。
一旦正确定义了子类,就可以使用点表示法引用属性和关系,而无需使用valueForKey
和setValueForKey
:
所以:
let Subject = NSManagedObject(entity: entitySubject!, insertIntoManagedObjectContext: context)
会变成:
let subject = Subject(entity: entitySubject!, insertIntoManagedObjectContext: context)
(请注意,变量应以小写字母开头-类和实体名称以大写字母开头)。
Grade.setValue(vakken.last!.cijfer[j], forKey: "cijfer")
变成:
grade.cijfer = vakken.last!.cijfer[j]
和
let firstObjectGrades = firstObject.valueForKey("grades")
变成:
let firstObjectGrades = firstObject.grades
同样,addTagObject
和removeTagObject
功能将使管理多对多关系更加容易。您的代码当前具有:
Subject.setValue(NSSet(object: Grade), forKey: "grade")
这将用对象替换Subject
该Grade
对象的任何现有成绩:不会将其添加到现有对象中。实际上,对于一对多关系,管理逆向(一对一)关系要容易得多:
grade.subject = subject
CoreData将自动为您处理逆向(一对多)关系。
如何删除其中一个成绩?
首先,不要为每个Grades
属性构建单独的数组:只需为一个属性创建一个数组Grades
:
var vak: Subject! {
didSet {
// Update the view.
grades = vak.grades.allObjects as! [Grade]
self.tableView.reloadData()
}
}
var grades: Array<Grade>!
您可以随时轻松获得属性。例如,cellForRowAtIndexPath
您可能会遇到以下情况:
let grade = grades[indexPath.row]
let cijfer = grade.cijfer
let weging = grade.weging
// populate cell labels etc using "cijfer" and "waging"
commitEditingStyle
然后,您可以轻松找到Grade
要删除的内容,并进行相应处理:
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
let grade = grades[indexPath.row]
// either remove the Grade from your Subject (which leaves
// the Grade "orphaned"):
grade.subject = nil
// or (probably better) completely delete the grade:
managedobjectcontext.deleteObject(grade)
// then remove it from the "grades" array:
grades.removeAtIndex(indexPath.row)
// and finally delete the corresponding table view row
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
// wrap up by saving the changes to the context:
do{
try mangedobjectcontext.save()
}catch{
print("error")
}
}
}
当我只更改变量之一时,如何将vak(subject)保存到上下文?
每当您保存上下文时,它都会将所有更改保存到向其注册的任何对象(插入到上下文中或使用上下文获取)。因此,即使您所做的唯一更改是修改one的一个属性Subject
,也只需调用save()
上下文。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句