2016-02-12 3 views
4

Я искал дни о том, как работать с одним или несколькими отношениями. Но я не могу понять.Основные данные от одного до многих отношений в swift

Я работаю над приложением, которое хранит оценки предмета. Таким образом, у одного субъекта есть много отношений с оценками. Все данные в настоящее время хранятся в массиве.

var vakken: [(naam:String, voorkeurGemiddelde:Double, wegingGemiddelde:Double, cijfer:[Double], weging:[Double], gemiddelde:Double)] = []
В тех случаях, когда [Double] - Cijfer и wege - являются признаками класса.

dataModel

Я в настоящее время имеют следующие для сохранения данных:

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. В некоторых учебниках я видел, что использование: var vakken = [NSManagedObject](), а затем использовать его в виде таблицы.
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 как я могу относиться к атрибутам и в большинстве в частности, оценки.

Я также сортирую массив по имени, который может быть A-Z или Z-A, и я сортирую по среднему значению, которое может быть 10-1 или 1-10. У меня есть код для сортировки в моем массиве.
4. Но я не знаю, как сортировать это с основными данными.

Я также видел учебник, в котором они сделали класс для атрибутов link. Так что я сделал один мой сам:

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. Но я не знаю, если мне нужно, ни как его использовать?

Если у вас есть какие-либо советы, советы, знайте хорошие учебники или знаете один из этих вопросов. Ваша помощь будет оценена по достоинству.

Если вам нужна дополнительная информация, просто дайте мне знать. :)

Update:

У меня есть этот код, чтобы получить объект предметной ведьмы щелкает.

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) в контексте, когда я просто изменяю собственную переменную?

так: vak.gemiddelde = newgemiddelde

+0

Я не думаю, что вы намерены использовать AppDelegate(), поскольку это приведет к инициализации нового экземпляра вашего AppDelegate, скорее, я думаю, вы имеете в виду «let appDelegate = UIApplication.sharedApplication(). Делегировать как! AppDelegate ", так как это получит текущий экземпляр AppDelegate вашего приложения. – beyowulf

+0

Appdelegate() - это функция, возвращающая appdelegate. Так что не беспокойтесь. – Cing

ответ

5

Чтобы решить ваши вопросы прямо:

Я использую данные в Tableview. В некоторых учебниках я видел, что использование: var vakken = [NSManagedObject](), а затем использовать его в виде таблицы. ли это возможно с моделью у меня есть, и я должен использовать его

Это, конечно, возможно, но это, вероятно, будет лучше использовать NSFetchedResultsController (см Apple Docs). Это специально предназначено для упрощения заполнения таблицыView данными из Core-Data.

Прежде всего я решил просто сохранить данные, когда приложение завершится, поэтому у меня будет код в делегате приложения, а затем просто извлеките его, когда приложение запустится. Как я могу получить массив в appdelegate, и это будет умным?

Я бы не заполнил/не сохранил массив в App Delegate. Некоторые люди следуют за шаблонами Apple, которые строят стек CoreData в App Delegate; другие имеют отдельный класс, который они создают для управления стеком. С точки зрения вашего кода в настоящее время он использует первый. Ваш взгляд контроллеры могут затем получить NSManagedObjectContext из App делегата с помощью:

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") 

Есть более эффективные способы, хотя: см. ваш последний вопрос ниже.

Я также сортирую массив по имени, который может быть A-Z или Z-A, и я сортирую по среднему значению, которое может быть 10-1 или 1-10. У меня есть код для сортировки в моем массиве. Но я не знаю, как сортировать это с основными данными.

Проще всего отсортировать данные при их получении. Для этого указать NSSortDescriptor (см Apple Docs) для выборки:

let fetchRequest = NSFetchRequest(entityName: "Subject") 
fetchRequest.sortDescriptors = [NSSortDescriptor(key:"name", ascending:true) 

Я также видел учебник, где они сделали класс для атрибутов. Я не знаю, нужна ли мне это или как ее использовать?

Да, используйте его. Это сделает жизнь намного проще. Вместо того, чтобы писать собственное определение класса, воспользуйтесь опцией меню Xcode «Создание подклассов NSManagedObject» в редакторе модели данных. Он создаст для вас код класса и также установит для каждого объекта Entity соответствующий класс. (Если вы хотите придерживаться своего собственного кода, вам нужно будет изменить «класс» для каждого объекта в редакторе модели данных).

После того как вы подклассы правильно определены, вы можете ссылаться на атрибуты и отношения, используя точечную нотацию, а не необходимости использовать 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 функции сделают легче управлять ко многим отношений Типы onship. Ваш код в настоящее время:

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) в контексте, когда я просто изменяю одну из переменных?

Всякий раз, когда вы сохраните контекст, он сохраняет все изменения каких-либо объектов, зарегистрированных с ним (вставленных в него или извлекаемые с помощью его). Таким образом, даже если единственное изменение, которое вы сделали, это изменить один атрибут одного Subject, просто позвоните save() по контексту.

+0

Можно ли получить оценку класса в теме, потому что vak.grades, похоже, являются только отношениями? – Cing

+1

Уверен - вернитесь к использованию 'valueForKeyPath': как это' let cijfers = subject.valueForKeyPath ("grades.cijfer") '. – pbasdf

+0

но как я буду получать индивидуальные номера, так как cijfers [0] врезается – Cing

Смежные вопросы