2014-07-15 3 views
23

J'ai une classe NSManagedObjectComment affecter une relation plusieurs-à-plusieurs CoreData dans Swift?

class Disease: NSManagedObject { 
    @NSManaged var diseaseId: String 
    @NSManaged var diseaseName: String 
    @NSManaged var dogBreed: NSSet 
} 

Comment puis-je ajouter une nouvelle relation à dogbreed? Si je change de type de var à NSMutableSet, les modifications ne sont pas enregistrées dans la base de données. Des idées?

+0

plus d'info http://stackoverflow.com/questions/24146524/setting-an-nsmanagedobject-relationship-in-swift – DogCoffee

+0

Pour d'autres qui trouvent cette question parce qu'ils veulent apprendre à utiliser les relations dans les données fondamentales , j'ai finalement trouvé ce tutoriel: [Core Data et Swift: Relations et plus de récupération] (http://code.tutsplus.com/tutorials/core-data-and-swift-relationships-and-more-fetching--cms- 25070) – Wraithbone

Répondre

20

Au Xcode 7 et Swift 2.0, les release note 17583057 états:

L'attribut NSManaged peut être utilisé avec des méthodes ainsi que propriétés, pour l'accès à généré automatiquement de base de données Key- Codeurs de valeur conformes à de nombreux accesseurs.

@NSManaged var employees: NSSet 

@NSManaged func addEmployeesObject(employee: Employee) 
@NSManaged func removeEmployeesObject(employee: Employee) 
@NSManaged func addEmployees(employees: NSSet) 
@NSManaged func removeEmployees(employees: NSSet) 

Ceux-ci peuvent être déclarés dans votre sous-classe NSManagedObject.(17583057)

Donc, il vous suffit de déclarer les méthodes et CoreData suivantes se chargeront du reste:

@NSManaged func addDogBreedsObject(dogBreed: DogBreed) 
@NSManaged func removeDogBreedsObject(dogBreed: DogBreed) 
@NSManaged func addDogBreeds(dogBreeds: NSSet) 
@NSManaged func removeDogBreeds(dogBreeds: NSSet) 
+1

Merci pour ça! + 100 – DogCoffee

+1

Cela pourrait être étrange et tardif, mais comment Swift sait-il prendre soin du reste? Vous ne spécifiez pas à quel ensemble les fonctions doivent s'ajouter? – Emptyless

+2

@Emptyless Cela a peu à voir avec Swift. Ces méthodes sont générées par CoreData, c'est la classe NSManaged qui en prend soin. Les réponses ci-dessus expliquent juste la bonne façon de le faire avec Swift. C'est assez similaire à déclarer IBOutlets dans UIViewControllers, et vous vous demandez comment Swift sait comment lier cela au Storyboard (ce n'est pas Swift non plus, c'est UIKit) – Nycen

18

Swift ne peut pas générer d'accesseurs d'exécution dynamiques en raison d'un système de type strict. Vous pouvez créer une extension de Disease classe et ajouter des méthodes manquées manuellement, voici le code:

extension Disease { 
    func addDogBreedObject(value:DogBreed) { 
     var items = self.mutableSetValueForKey("dogBreed"); 
     items.addObject(value) 
    } 

    func removeDogBreedObject(value:DogBreed) { 
     var items = self.mutableSetValueForKey("dogBreed"); 
     items.removeObject(value) 
    } 
} 

Remarques:

Je vous suggère de créer un fichier séparé pour l'extension Disease+CoreData.swift, Cela devrait aider à garder votre code de redéfinit lorsque vous générez à nouveau le modèle CoreData.

Il suffit de créer une relation dans l'un des objets gérés, le second sera mis à jour avec la référence arrière. (Identique à Objective-C)

Important: Pour que tout fonctionne, vous devez vérifier que les noms de classe des entités de votre modèle CoreData incluent le nom de votre module. Par exemple. MyProjectName.Disease

Réponse inspirée: Setting an NSManagedObject relationship in Swift

+1

J'ai trouvé que ce code ne fonctionnerait pas pour mon application sans encapsuler le processus de réglage dans le code d'observation de valeur de clé, avec self.willChangeValueForKey ("key", withSetMutation: , usingObjects: ) et la méthode didChangeValueForKey correspondante. Sans cela, toutes sortes d'erreurs étranges et apparemment sans rapport ont été signalées. – Ash

+0

Bon point. Je vais tester votre suggestion et ajouter à la réponse quand de retour à mon bureau de développement. – Keenle

10

Si vous êtes à la recherche d'une approche simple il suffit d'utiliser cela.

import CoreData 
extension NSManagedObject { 
    func addObject(value: NSManagedObject, forKey: String) { 
     var items = self.mutableSetValueForKey(forKey); 
     items.addObject(value) 
    } 
} 

La mise en œuvre:

department.addObject(section, forKey: "employees") 

Au lieu d'écrire la même méthode sur toutes les classes NSManageObject qui en a besoin.

+0

Ah ah - J'aime cette solution. Soigné. –

2

Dans le prolongement de @Naz. Et en combinaison avec le commentaire de @ Ash. J'ai trouvé la seule solution de travail pour Xcode 6.3.1

import CoreData 

extension NSManagedObject { 
    func addObject(value: NSManagedObject, forKey: String) { 
     self.willChangeValueForKey(forKey, withSetMutation: NSKeyValueSetMutationKind.UnionSetMutation, usingObjects: NSSet(object: value) as Set<NSObject>) 
     var items = self.mutableSetValueForKey(forKey); 
     items.addObject(value) 
     self.didChangeValueForKey(forKey, withSetMutation: NSKeyValueSetMutationKind.UnionSetMutation, usingObjects: NSSet(object: value) as Set<NSObject>) 
    } 
} 

Vous devez appeler les gestionnaires willChange et didChange afin d'ajouter correctement un objet à une relation à plusieurs dans Swift.

myManagedObject.addObject(value, forKey: "yourKey") 
4

En fait, vous pouvez simplement écrire:

@NSManaged var dogBreed: Set<DogBreed> 

Et utiliser la insert et remove directement des méthodes Set.

2

@Nycen a la meilleure solution pour Xcode 7 avec les méthodes, note cependant maintenant mis en œuvre automatiquement que la question NSOrderedSet existe presque toujours incroyablement (voir this question), donc si vous utilisez un NSOrderedSet pour votre relation au lieu d'un NSSet vous aurez toujours besoin d'utiliser une solution de contournement.

(j'aurais commenté au lieu de poster une nouvelle réponse, mais je manque en points)

+0

Je ne peux pas croire que c'est toujours un bug. Peut-être que dans une semaine ou deux, ils vont le réparer à la WWDC. –

1

Si vous avez besoin d'utiliser un NSOrderedSet au lieu de NSSet, je l'ai utilisé le code suivant qui le rend plus facile pour obtenir les méthodes NSMutableOrderedSet pour ajouter, insérer et supprimer des objets.

@NSManaged private var myOrderedSet: NSOrderedSet 

var myMutableOrderedSet: NSMutableOrderedSet { 
    return self.mutableOrderedSetValueForKey("myOrderedSet") 
} 
Questions connexes