J'ai créé une entité simple "CDWorkout" avec un attribut "nom" dans CDModel.xcdatamodeld. Le nom du conteneur dans AppDelegate est également 'CDModel'. La classe Codegen pour 'CDWorkout' est la catégorie/extension. Voici le code pour la classe CDWorkout:
class CDWorkout: NSManagedObject {
class func createWorkout(workoutInfo : Workout, in context: NSManagedObjectContext) -> CDWorkout{
let workout = CDWorkout(context: context)
workout.name = "anyName"
return workout
}
}
la fonction createWorkout est appelée depuis un autre viewController avec un argument contextuel tel que container.viewContext
mais se bloque immédiatement avec le message suivant:
Arrêt de l'application en raison d'une exception non interceptée 'NSInvalidArgumentException', raison: 'Un objet NSManagedObject de classe' Workout_Generator.CDWorkout 'doit avoir une description NSEntityDescription valide'
Qu'est-ce que j'ai oublié?
Le problème était que je n'avais pas vérifié Class Module: module de produit actuel pour CDWorkout Entity.
Dans mon cas, le même problème se trouvait dans le modificateur @objc dans l'en-tête généré automatiquement par la classe de données.
@objc(CachedMovie)
public class CachedMovie: NSManagedObject {
Je viens de retirer @objc(CachedMovie)
et cela a commencé à fonctionner
J'ai eu un problème mineur stupide qui a entraîné la même erreur. J'étais en train d'initialiser NSPersistentContainer avec un nom incorrect.
Il devrait porter le même nom que le fichier source portant l’extension .xcdatamodeld . par exemple. modelFileName.xcdatamodelId
let persistentContainer = NSPersistentContainer(name: "modelFileName")
Je suis tombé sur le même message d'erreur lors de la tentative d'insertion/ajout d'un objet géré à partir d'une extension (SiriKit). Il semble y avoir eu un problème d'espace de noms de l'extension ne correspondant pas au fichier .xcdatamodeld
, car je créais la description de l'entité à l'aide de MyClass.entity()
.
La combinaison qui a fonctionné pour moi était:
@objc(MyClass)
en haut de chaque sous-classe NSManagedObject
let entity = NSEntityDescription.entity(forEntityName: "MyClass", in: context)!
il est facile de répondre à cette question. sans enlevé
@objc(Workout)
la solution est sur documentaire Programmation des données de base sur "Nom de l’entité et Nom de la classe" . ici dans votre Xcode avant de le faire (Editor -> Create NSManagedObject SubClass) doit changer le nom de la classe des entités pour ajouter "MO", CoreData peut différencier le nom de la classe du nom de l’entité. et le
@objc(Workout)
ne sera pas créé, donnez-nous celui-ci:
class CDWorkoutMO: NSManagedObject {
class func createWorkout(workoutInfo : Workout, in context: NSManagedObjectContext) -> CDWorkoutMO {
let workout = CDWorkoutMO(context: context)
workout.name = "anyName"
return workout
}
}
Vous devez créer un nouveau NSManagedObject
avant de pouvoir l'utiliser.
let workout = NSEntityDescription.insertNewObjectForEntityForName("CDWorkout",
inManagedObjectContext: context) as! CDWorkout
vous pouvez maintenant définir le nom comme vous l'avez fait: workout.name = "any_name"
vous pouvez vous référer à Documentation CoreData pour plus d’informations sur CoreData
L’erreur que j’ai faite est de changer le nom de l’entité et de la "Sous-classe NSManagedObject" générée sans mettre à jour le nom de la classe. Comment réparer:
J'ai eu un problème similaire dans la pile CoreData avec NSManagedObjectModel
fabriqué à partir de code Swift
. Le problème se trouvait dans mauvaise valeur pour l'attribut NSEntityDescription.managedObjectClassName
. Le préfixe Swift module
a été oublié.
Configuration correcte:
let entity = NSEntityDescription()
entity.name = PostEntity.entityName // `PostEntity`
entity.managedObjectClassName = PostEntity.entityClassName // `MyFrameworkName.PostEntity`
entity.properties = [....]
Où: entityName
et entityClassName
définis comme ceci.
extension NSManagedObject {
public static var entityName: String {
let className = NSStringFromClass(self) // As alternative can be used `self.description()` or `String(describing: self)`
let entityName = className.components(separatedBy: ".").last!
return entityName
}
public static var entityClassName: String {
let className = NSStringFromClass(self)
return className
}
}
J'essayais d'ajouter CoreData à un projet existant et j'ai renommé beaucoup de choses. Je me suis retrouvé avec plusieurs .xcdatamodeld sans le savoir. La solution consistait à supprimer .xcdatamodeld et à générer NSManagerObject, puis à le recréer.