web-dev-qa-db-fra.com

Comment se fait-il que je puisse caster sur NSManagedObject mais pas sur le type de mon entité?

J'utilise le Swift standard pour les données de base dans un nouveau projet. Mon fichier .xcdatamodeld A une seule entité définie (Task) avec un seul attribut (name).

J'ai un fichier Task.Swift Qui ressemble à ceci:

import CoreData

class Task: NSManagedObject {
    @NSManaged var name: String
}

Lorsque je lance cela, cela fonctionne:

var firstTask = NSEntityDescription.insertNewObjectForEntityForName("Task",
    inManagedObjectContext: managedObjectContext) as NSManagedObject

firstTask.setPrimitiveValue("File my TPS reports", forKey: "name")

var error: NSError?

managedObjectContext.save(&error)

Je peux même aller dans la base de données SQLite utilisée par le simulateur iOS et confirmer que la ligne a été ajoutée.

Cependant, lorsque j'exécute exactement le même code que ci-dessus mais avec as Task Au lieu de as NSManagedObject, J'obtiens un plantage avec le message d'erreur Thread 1: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0), associé au var firstTask… Ligne. Si je continue l'exécution, j'obtiens EXC_BAD_ACCESS Et 0 misaligned_stack_error_ En haut du fil 1 chaque fois que je le fais avancer.

Pourquoi cette distribution pourrait-elle mener à tout cela?

35
William Proffitt

Assurez-vous que le champ Nom de votre classe est bien Module. Tâche, où Module est le nom de votre application. Les classes CoreData dans Swift sont des espaces de noms. À l'heure actuelle, votre objet est extrait du contexte en tant que NSManagedObject, pas en tant que tâche, donc la conversion échoue.

46
Ben Gottlieb

C'est même frustré si vous avez essayé toutes les suggestions ci-dessus et qu'aucune d'entre elles ne travaille pour moi !!

Voilà donc ce qui fonctionne pour moi.

1- Sélectionnez votre fichier xcdatamodeld

2- Assurez-vous que toutes vos entités n'ont pas de module dans le "Data Model Inspector", si vous voyez "Model: Current Product Module" ... effacez-le pour qu'il ressemble à l'image jointe.

3- Supprimez votre application pour effacer les données de base

4- Si cela ne fonctionne toujours pas, supprimez vos entités et régénérez-les.

enter image description here

28
polarwar

Vous devez modifier votre fichier Task.Swift. Ajout de @objc (tâche) comme ci-dessous

import CoreData

@objc(Task)
class Task: NSManagedObject {
    @NSManaged var name: String
}

Je pense que c'est un bug si votre projet ne contient pas de codes objective-c. Cependant, vous devez ajouter cette ligne jusqu'à ce que cela soit résolu.

Je l'ai appris d'ici.

vidéo Youtube à 11:45

12
Owen Zhao

Je suppose que seul le changement du champ de classe dans le .xcdatamodel ne fonctionne plus car j'ai toujours l'exception suivante: erreur fatale: utilisation de l'initialiseur non implémenté 'init (entity: insertIntoManagedObjectContext :)' pour la classe

J'ai donc entré ce code dans ma classe personnalisée:

    init(entity: NSEntityDescription!,
    insertIntoManagedObjectContext context: NSManagedObjectContext!) {
        super.init(entity: entity, insertIntoManagedObjectContext: context)
}

Du coup, ça a marché! NSManagedObject peut désormais être converti dans ma classe personnalisée. Je ne comprends pas vraiment pourquoi c'est la solution, mais ça marche :)

6
Jovan Jovanovski

Une mise à jour pour @Ben Gottlieb réponse sous XCode 7.1 et Swift 2.0

  1. ajoutez @objc à votre classe. Voir la réponse d'Owen Zhao. Ce qui suit est un exemple:
@objc
class ImageRecordMO: NSManagedObject{
  1. Ouvrez votre fichier .xcdatamodled.

  2. Sélectionnez votre entité et cliquez sur l'inspecteur de modèle de données dans le panneau de droite.

  3. Entrez le nom de la classe, voir la figure ci-dessous

  4. Sélectionnez votre module comme module de produit actuel, voir la figure ci-dessous.

enter image description here

5
Anson Yao

Xcode 7 + Swift 2

Person.Swift

@objc(Person)
class Person: NSManagedObject {
}

Modèle de données

enter image description here

Ensuite, appelez simplement

let person = NSEntityDescription.insertNewObjectForEntityForName("Person", inManagedObjectContext: self.managedObjectContext) as! Person
4
Viktor Kucera

J'ai dû ajouter @objc () et définir la classe dans l'interface coredata . Dans la fenêtre droite de CoreData, dans la zone Entité, il y a la zone de texte Nom et Classe. La classe ne doit pas être MSManagedObject mais plutôt votre classe . J'ai créé un exemple de travail simple !

2
Nicolas Chaussin

J'ai rencontré ce problème au cours des derniers jours et, étrangement, la solution qui a fonctionné pour moi était une variante de celle suggérée ci-dessus.

J'ai ajouté la déclaration @objc aux sous-classes générées, mais j'ai supprimé tout préfixe d'espace de noms dans le nom de classe dans le modèle d'objet (il avait un préfixe par défaut "PRODUCT_MODULE_NAME." Après la génération des sous-classes). Ça a marché.

1
Julien Couvreur