2016-06-02 17 views
2

ich eine Kerndaten App mit dem Modell Setup genau wie das Bild unten:Wie Core-Datenbeziehungen in einem einzigen NSFetchRequest abgerufen werden?

Core Data Model

Die Beziehungen sind Setup wie folgt aus:

Kategorie < - >> Unter < - >> Artikel

Jetzt ist es möglich, in einem einzigen Abruf Objekte von Unterkategorie und Artikel-Entities zu erhalten, die das gleiche Attribut namens categoryName haben? Ich denke, es kann mit Beziehungen gemacht werden, aber der Code ich verwende nicht funktioniert denen:

let fetchNote = NSFetchRequest(entityName: "Category") 
    fetchNote.predicate = NSPredicate(format: "ANY subcategory.name == %@ AND item.name == %@", "Badaue", "Badaue") 
    let notes = try! appDel.managedObjectContext.executeFetchRequest(fetchNote) as? [Category] 
    print(notes) 
+0

Was funktioniert nicht? – Koen

+0

Bitte klären Sie, welche Entität Sie abzurufen versuchen - jeder Abruf liefert ein Array mit * entweder * Category-Objekten, * oder * Unterkategorie-Objekten, * oder * Objekt-Objekten, aber * nicht * einem Mix verschiedener Entitäten. – pbasdf

+0

Sicher. Ich möchte die Category-Entität abrufen und Ergebnisse von Subcategory- und Item-Entitäten abrufen, für die beispielsweise das Attribut "categoryName" den Wert "Badaue" hat. –

Antwort

0

Um Verwirrung zu vermeiden, würde ich vorschlagen item zu items Umbenennung zu reflektieren, dass es eine n-Beziehung . Gleiches gilt für subcategory.

EDIT2 - Sie bitten um die Subcategory und Item Objekte, die eine bestimmte categoryName haben, richtig? Die Abfrage, die Sie oben geschrieben haben, macht das überhaupt nicht.

Erstens, ja, Sie werden 2 Abfragen benötigen, da Sie nur 1 Entity Typ gleichzeitig abrufen können.

Zweitens, lassen Sie uns Ihre Syntax neu schreiben, weil es gerade jetzt sehr gefährlich ist.

do { 
    let predicate = NSPredicate(format: "categoryName == %@", "yourCategoryHere") 
    let fetchSubcategory = NSFetchRequest(entityName: "Subcategory") 
    fetchSubcategory.predicate = predicate 
    if let subCategoryResults = try context.executeFetchRequest(fetchSubcategory) as? [Subcategory] { 
    //do stuff 
    } 
    let fetchItem = NSFetchRequest(entityName: "Item") 
    fetchItem.predicate = predicate 
    if let itemResults = try context.executeFetchRequest(fetchItem) as? [Item] { 
    //do stuff 
    } 
}catch { 
    print(error) 
} 
+0

Die App hält an und wenn ich einen Ausnahme-Breakpoint einstelle, zeigt sie auf diese Codezeile: Let notes = try! appDel.managedObjectContext.executeFetchRequest (fetchNote) als? [Kategorie], aber es werden keine Zeichen auf dem Protokollbildschirm ausgegeben. –

+0

Und wenn ich den Ausnahme-Breakpoint deaktivieren, ist das Ausgabe-Protokoll: *** Beenden App aufgrund der nicht abgefangenen Ausnahme 'NSInvalidArgumentException', Grund: 'zu-viele Schlüssel nicht erlaubt hier' –

+0

Es ist wie ich vermutete - Sie können nicht abfragen to-many-Beziehung einer to-many-Beziehung. Sie müssen zwei separate Abfragen schreiben. – sschale

0

Wenn Sie Categories holen Sie werden eine Reihe von Category Objekte erhalten. Jedes dieser Objekte hat eine Eigenschaft subcategory, die ein Satz ist, der alle zugehörigen Objekte Subcategory enthält. Und jedes dieser Objekte wird eine Eigenschaft haben, item, die ein Satz ist, der alle Item Objekte enthält, die zu diesem Subcategory gehören. Die zugehörigen Objekte sind innerhalb der Objekte Category und Subcategory "verschachtelt".

Wenn Sie die Kategorien abrufen, müssen Sie kein Prädikat angeben, um die zugehörigen Objekte abzurufen. Sie werden automatisch abgerufen, sobald Sie auf die Eigenschaften subcategory oder item zugreifen. So zum Beispiel, wenn myCategory ist ein Category Objekt, das Sie geholt haben,

let mySubcategories = myCategory.subcategory 
for subcat in mySubcategories { 
    print("\(subcat)") 
} 

jeder der zugehörigen Unterkategorien gedruckt werden soll.

Wenn diese Eigenschaften null sind, haben Sie möglicherweise noch keine Beziehungen hergestellt. Dies geschieht normalerweise, wenn Sie die Objekte zum ersten Mal erstellen. Erstellen Sie zum Beispiel, wenn Sie ein Subcategory mit categoryName = "Badaue", könnte man die Beziehung mit dem Category mit name = "Badaue" wie folgt begründen:

let newSubcategory = .... 
newSubcategory.categoryName = "Badaue" 
let fetchCategory = NSFetchRequest(entityName: "Category") 
fetchCategory.predicate = NSPredicate(format: "name == %@", newSubcategory.categoryName) 
let categories = try! appDel.managedObjectContext.executeFetchRequest(fetchNote) as? [Category] 
if (categories!.count > 0) { 
    let firstCategory = categories[0] 
    newSubCategory.category = firstCategory 
} else { 
    // no existing Category with the correct name, so create one.... 
    let newCategory = .... 
    // ... and then establish the relationship to the Subcategory 
    newSubCategory.category = newCategory 
} 
0

Sollte wie diese versuchen: Ich habe zwei Entitäten 1. Auslöser 2. Zahlen Relation ist Many-to-Many: - Einem Trigger können eine oder mehrere Mobilnummern angehängt sein, während die Nummer Teil von mehr als einem Trigger in der Trigger-Tabelle sein kann.

Schritt: 1

enter image description here

Schritt: 2

enter image description here

Jetzt würden Sie Situation wie dieses:

enter image description here

Der von Xcode generierte Code ist wie folgt.

import Foundation 
import CoreData 


extension MobileNumber { 

@nonobjc public class func fetchRequest() -> NSFetchRequest<MobileNumber> { 
    return NSFetchRequest<MobileNumber>(entityName: "MobileNumber"); 
} 

@NSManaged public var mNumber: String? 
@NSManaged public var title: String? 
@NSManaged public var triggers: NSSet? 

} 

// MARK: Generated accessors for triggers 
extension MobileNumber { 

@objc(addTriggersObject:) 
@NSManaged public func addToTriggers(_ value: Trigger) 

@objc(removeTriggersObject:) 
@NSManaged public func removeFromTriggers(_ value: Trigger) 

@objc(addTriggers:) 
@NSManaged public func addToTriggers(_ values: NSSet) 

@objc(removeTriggers:) 
@NSManaged public func removeFromTriggers(_ values: NSSet) 

}

In ähnlicher Weise werden Sie auch für andere Entitäten Klassen erzeugt haben. Ich habe eine Funktion zum Abrufen einer Entität mit UUID definiert, die für alle Zeilen meiner Trigger-Tabelle immer eindeutig ist.

func fetchTriggerWithUUID(identifier: String) -> [Trigger] 
    { 
    let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Trigger") 
    let predicate = NSPredicate(format: "uuid = %@", identifier) 

    fetchRequest.predicate = predicate 

    do { 

     let results = try managedObjectContext.fetch(fetchRequest) as! [Trigger] 

     return results 

    } catch let error as NSError { 

     print(error) 

    } 

    return [] 
} 

Jetzt, wo ich brauche mit Daten einer bestimmten [Zeile] zu spielen, oder Sie können auch mit einer Reihe von [Zeilen], das ist so einfach, hier in meinem Fall.

let result = AppDelegate.getAppDelegate().fetchTriggerWithUUID(identifier: notifIdentifier).first 

     numbers.removeAll() 

     for num in (result?.numbers)! 
     { 
      let numHere = num as! MobileNumber 
      numbers.append(numHere.mNumber!) 


     } 

     let messageHere = "Wanted to inform you! \n" + (result?.title)! + "\n" + (result?.desc)! 

Sie können so viele Entitäten verwenden, die Sie in Ihrer [.xcdatamodelID] -Datei haben.