Impossible de créer un NSPersistentStoreCoordinator avec un modèle nul

96

J'ai eu ma première fissure chez Core Data et j'obtiens l'erreur suivante lors de l'exécution de mon code sur mon appareil, mais cela fonctionne bien sur le simulateur.

* Arrêt de l'application en raison d'une exception non interceptée 'NSInvalidArgumentException', raison: 'Impossible de créer un NSPersistentStoreCoordinator avec un modèle nul'

Certaines de mes méthodes qui pourraient causer le problème:

    - (NSManagedObjectContext *)managedObjectContext
{
    if (__managedObjectContext != nil)
    {
        return __managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil)
    {
        __managedObjectContext = [[NSManagedObjectContext alloc] init];
        [__managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return __managedObjectContext;
}

/**
 Returns the managed object model for the application.
 If the model doesn't already exist, it is created from the application's model.
 */
- (NSManagedObjectModel *)managedObjectModel
{
    if (__managedObjectModel != nil)
    {
        return __managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"RugbyOnTv" withExtension:@"momd"];
    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    
    return __managedObjectModel;
}

/**
 Returns the persistent store coordinator for the application.
 If the coordinator doesn't already exist, it is created and the application's store added to it.
 */
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (__persistentStoreCoordinator != nil)
    {
        return __persistentStoreCoordinator;
    }

    NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"RugbyOnTV.sqlite"];

    NSURL *storeUrl = [NSURL fileURLWithPath:storePath];

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];    
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

    NSError *error = nil;
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];


    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    

    return __persistentStoreCoordinator;
}


    - (NSString *)applicationDocumentsDirectory {

        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
        return basePath;
    }

ÉDITER

J'ai copié et collé la méthode managedObjectContext (ci-dessous) à partir des CoreDataBooks d'Apple et cela fonctionne maintenant ... Je ne sais pas vraiment pourquoi.

- (NSManagedObjectModel *)managedObjectModel {
    if (managedObjectModel != nil) {
        return managedObjectModel;
    }
    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
    return managedObjectModel;
}
Dominic Williams
la source
Hé, cela pourrait être aussi simple que d'ajouter le mot "Model" au premier paramètre URLForResource .... ouais, j'ai eu le même problème. Ensuite, j'ai vérifié le contenu réel du .app dans la ligne de commande et j'ai découvert que le .momd était en cours de création. Alors essayez ceci: [[NSBundle mainBundle] URLForResource: @ "RugbyOnTvModel" withExtension: @ "momd"];
PostCodeism
NSString *basePath = [paths firstObject];
William Entriken

Réponses:

157

J'ai eu exactement le même message d'erreur que le message d'origine. J'ai lutté avec ça pendant des heures. C'était cette ligne dans mon AppDelegate.m.

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"[same with name of xcdatamodeld]" withExtension:@"momd"];

Pour tous ceux qui recherchent ce message d'erreur et trouvent ce fil .... essayez d'abord ceci.

Vous devez vous assurer que là où il est dit [même chose avec le nom de xcdatamodeld] .... c'est bien !!! Pour une raison quelconque, le mien contenait le nom de mon projet et non le nom du modèle de données.

Je l'ai changé et cela a fonctionné tout de suite .....

Merci à Rock & Muller pour votre contribution ... vous m'avez sauvé des jours !!

Gaz.

Gareth Lloyd
la source
2
C'est le commentaire qui m'a aidé. Le nom magique que mon application recherchait était le blahde blah.xcdatamodeld. Merci internet et stackoverflow.
acedanger
J'ai "Model.xcdatamodeld", changé en "Model" comme argument. Mais Xcode refuse de le charger, mais ce fichier est en fait là! Je ne sais pas ce qui se passe.
Darmen Amanbayev
Sensationnel. Merci me cognait la tête pendant un moment.
Sani Elfishawy
qu'en est-il du storeURL one?
MoralCode
54

vérifier d'abord:

NSLog(@"%@", [self managedObjectModel]);

Si vous obtenez une valeur nulle, le problème est peut-être là

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"RugbyOnTv" withExtension:@"momd"];

Alors, essayez de changer @ "momd" par @ "mom"

D33pN16h7
la source
1
Tu as raison. Il est nul et donc cette ligne provoque l'erreur: `__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];` Changer pour maman ne semble pas résoudre quoi que ce soit
Dominic Williams
3
Très probablement modelURLaussi nil. La cause la plus fréquente est une faute de frappe RugbyOnTv. Notez que cela est sensible à la casse.
Rob Napier
1
Changer «maman» en «maman» a aussi fonctionné pour moi. Merci. Mais pourquoi? Pourquoi XCode génère-t-il du code qui ne fonctionne pas? Pourquoi ai-je trouver des correctifs obscurs comme celui-ci dans SO pour faire fonctionner les modèles de base?
Rhubarb
10
Ayant récemment présenté une 2ème version de mon modèle, j'ai dû le changer pour le faire revenir à momd. Étant donné que le conteneur de version de modèle a une extension de xdatamodeld, je pense que nous pouvons en déduire ce qui se passe ici. "momd" est pour les modèles avec plus d'une version tandis que "mom" est pour les modèles qui n'ont pas de versioning.
Gerald
2
J'ai copié du code dans un nouveau projet [iOS7] textuellement et c'était à l'origine maman, mais le changement pour maman l'a corrigé. Je ne sais pas comment j'aurais trouvé une solution sans cela, alors merci :)
Ian Clay
20

J'ai rencontré un problème étrange avec Xcode 4.3.2 et iOS 5.

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"NAME_OF_THE_MODEL" withExtension:@"momd"];

renvoie une URL valide mais

__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

renvoie un NSManagedObjectModel nul. Mais après avoir vérifié la documentation , il semble que NSManagedObjectModel ait besoin d'un fichier où NAME_OF_THE_MODEL.momd est un répertoire qui contient un fichier NAME_OF_THE_MODEL.mom. Changer l'URL en

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"NAME_OF_THE_MODEL" withExtension:@"mom" subdirectory:@"NAME_OF_THE_MODEL.momd"];

fonctionne alors. Cela semble étrange que Xcode génère du code qui ne fonctionne pas avec lui-même ...

Xster
la source
1
Ce problème spécifique est causé par la création d'une version de modèle supplémentaire, puis par une tentative de suppression manuelle pendant que Xcode est ouvert. Cela provoque une sorte de corruption. Vous ne devez pas transmettre de versions de modèle spécifiques dans le répertoire momd.
Mike Weller
cool @MikeWeller, bon à savoir. Savez-vous où se trouvent les métadonnées qui pointent vers le fichier maman dans le répertoire momd?
xster
Je n'essayais pas de le supprimer, mais j'avais ce problème et la solution publiée a fonctionné pour moi, en particulier, je viens d'ajouter une vérification pour voir si c'est toujours nul et si c'est le cas, j'ai ajouté ce code ci-dessus: if (_managedObjectContext == nil) {NSURL * modelURL = [[NSBundle mainBundle] URLForResource: @ "Model" withExtension: @ Sous-répertoire "mom": @ "Model.momd"]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL: modelURL]; }
David van Dugteren
19

J'ai eu ce problème et changer «maman» en «maman» n'a rien fait. Pour le réparer, j'ai dû faire un clic droit sur le fichier xcdatamodelId> afficher le contenu du package, puis supprimer le fichier .xcurrentversion caché.

PS: Ce problème n'a commencé à se produire qu'après avoir changé le nom du fichier de modèle de données.

JDx
la source
2
Pour tous ceux qui rencontrent le problème suivant: managedObjectModel étant nul après avoir renommé le fichier xcdatamodeld: cette réponse est la meilleure! Merci JDx, votre réponse m'a beaucoup aidé!
Dumoko
Au lieu de le supprimer, vous pouvez éventuellement le modifier afin de remplacer le nom de fichier stocké par la dernière version de youl xcdatamodel
furins
13

Une autre source de cette erreur est que parfois Xcode n'inclut pas le modèle de données dans la construction.

Vérifiez les phases de construction de votre cible et assurez-vous que le fichier * .xcdatamodeld est inclus dans la section Compiler les sources.

Dave Wood
la source
Cela a réglé le problème pour moi.
Ben Thomas
cela a fonctionné pour moi. C'est frustrant et difficile à déboguer quand il fonctionne sur Simulator et non sur un appareil réel!
Bishal Ghimire
9

Ce qui s'est probablement passé, c'est que votre fichier xcdatamodeld du code source d'Apple s'est transformé en un fichier xcdatamodel (sans le d) et donc ils ne sont pas considérés comme identiques.

Le moyen le plus rapide de résoudre ce problème est de sélectionner le fichier xcdatamodel dans le navigateur de votre projet et dans la barre de menus

Editor->Add Model Version...

et ajoutez une nouvelle version de votre modèle. Apportez toutes les modifications à la nouvelle version.

Cela fonctionne dans Xcode 5

Louis Cremen
la source
malheureusement cette option n'existe pas dans Xcode 5 .. voir ici
abbood
J'ai oublié de mentionner que vous devez sélectionner le fichier xcdatamodel. Réponse modifiée pour refléter le commentaire.
Louis Cremen
8

Je le résous en ajoutant le fichier db au fichier Copy Bundle Resources.

Allez à la racine de votre projet >> sélectionnez votre cible >> Phases de construction >> Copier les ressources du bundle. Assurez-vous que votre fichier xcdatamodeld a été ajouté ici.

entrez la description de l'image ici

Aucune des solutions affichées n'a fonctionné pour moi. Donc, j'espère que cet article aidera quelqu'un là-bas. Mon application plante uniquement dans les versions btw. Leçon apprise. Testez toujours les versions de version!

BTW, j'ai trouvé ce message SO le plus utile https://stackoverflow.com/a/6708837/951349 .

smileBot
la source
6

j'ai eu le même problème avec @Dominic Williams

essayez de changer le nom du fichier momd ci-dessous (vous pouvez le trouver dans la managedObjectModelméthode par défaut), qui est identique au [file name].xcdatamodeldfichier que vous avez créé:

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"[same with name of xcdatamodeld]" withExtension:@"momd"];
Roche
la source
5

J'ai eu le même problème. La solution était un mélange de 2 réponses:

1) J'ai dû ajouter le paramètre "sous-répertoire" dans l'appel URLForResource

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"DATAMODEL_NAME" withExtension:@"mom" subdirectory:@"DATAMODEL_NAME.momd"];

2) Pour une raison que je ne connais pas, le modèle de données n'a pas été inclus lors de la compilation du projet. J'ai dû l'ajouter manuellement dans les "Build Phases / Compile resources".

Avec une seule des solutions ci-dessus, mon application n'a pas fonctionné.

Salvador Ponticelli
la source
4

La solution au problème dont vous parlez est simple. Remplacez l'extension de fichier par "maman" au lieu de "momd" dans l'URL du modèle. Terminé.

pfuri
la source
4

J'ai essayé toutes les solutions ici, et aucune d'elles n'a fonctionné. Mon problème est apparu après avoir renommé le projet. Apparemment, Xcode continue de chercher l'ancien fichier momd au mauvais endroit pendant la compilation.

Pour tous ceux qui ont essayé toutes les solutions ci-dessus sans succès, essayez de vérifier le chemin complet de votre .xcdatamodeldfichier. C'est ce qui a fonctionné pour moi.

XCool
la source
4

J'ai eu le même problème, cela fonctionnait bien sur iOS6 mais pas sur iOS5. Voici comment je l'ai résolu:

  1. Créez une nouvelle version de modèle dans xcode. (sélectionnez .xcdatamodeld, ouvrez le menu Editeur et cliquez sur "Ajouter une version du modèle ...")
  2. Compilez et assurez-vous que la nouvelle version fonctionne.
  3. Définissez l'ancienne comme version actuelle. ("Actuel" dans l'inspecteur de fichiers pour le .xcdatamodeldmodèle de données de base sous version)
  4. Supprimer la référence au .xcdatamodeldfichier dans xcode
  5. Cliquez avec le bouton droit sur le .xcdatamodeldfichier dans le Finder et choisissez "Afficher le contenu du paquet"
  6. Supprimez le nouveau .xcdatamodelque vous ne voulez pas
  7. Ajouter à nouveau le .xcdatamodeldxcode
  8. Compilez et souriez

(C'est ici que j'ai trouvé comment supprimer une version de modèle: Comment supprimer une version de modèle de données ancienne / inutilisée dans Xcode )

Fredrik
la source
Tack så mycket! Cela a été très utile.
Michael Dorner
4

Je résous le problème sans changer de code.

J'ajoute le ModelName.xcdatamodeld via File-> Add File au lieu de faire glisser le fichier dans le Xcode.

 NSString *path=@"ModelName";

NSURL *modelURL = [NSURL fileURLWithPath:[path stringByAppendingPathExtension:@"momd"]];

model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
Chris So
la source
1

De mon côté, le problème était que j'avais changé la casse de quelques caractères dans le nom de la base de données.

Lors du démarrage d'un nouveau projet, Xcode configure automatiquement tout à partir du nom du projet. Si vous avez commencé à appeler votre projet "Rugbyontv" et que vous décidiez plus tard de changer pour "RugbyOnTV" et que vous faisiez une recherche et un remplacement, cela le briserait. (Merci à Rob pour avoir souligné que le nom est sensible à la casse)

Brian Gerfort
la source
1

Je cherche une réponse depuis des heures et rien n'a fonctionné. Mais j'ai soudainement trouvé cet article . Donc, selon cela, le problème était de définir le contrôleur racine dans cette partie d'AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    ListViewController *rootView = (ListViewController *)self.window.rootViewController;
    rootView.managedObjectContext = self.managedObjectContext;
    return YES;
}

En fait, vous devez définir quel contrôleur racine déléguera votre connexion CoreData. Et dans mon cas, j'avais un TabBarController connecté à d'autres vues, donc mon contrôleur racine de vue tarée a été défini comme TabBar et cela a provoqué une erreur. j'ai changé

ListViewController *rootView = (ListViewController *)self.window.rootViewController;

à

ListViewController *rootView = (ListViewController *)self.window.superview;

et tout a fonctionné.

Kokoko
la source
1

Je sais que cela ne résout pas votre problème mais j'ai rencontré ce problème hier qui m'a tourmenté pendant des heures, la solution publiée par @Dominic Williams m'a donné une ArrayIndexOutOfBoundsException (quel que soit l'équivalent Objective-C).

Je ne suis pas encore très bon avec Objective-C / Xcode mais je travaille sur une application iOS que notre société a (principalement) développée en externe. Malheureusement, ils oubliaient souvent comment utiliser un clavier et utilisaient des lettres majuscules de manière interchangeable ou épelaient les propriétés de manière incorrecte, mais étaient trop paresseux pour revenir en arrière et les modifier. Ils avaient utilisé une majuscule dans le nom du projet xcode là où elle n'était pas censée être (notre nom de produit n'utilise pas de majuscule) et j'ai dû revenir en arrière et changer chaque occurrence de cette lettre majuscule en minuscule ; qui comprenait le nom du projet, le fichier de données de base, des centaines de variables, etc.

Quoi qu'il en soit, une fois que j'ai fait cela, j'ai rencontré cette erreur et aucune solution ne l'a corrigée pour moi. Je m'étais assuré que tous les noms d'URL étaient corrects, le projet nettoyé, l'application désinstallée, le téléphone redémarré, etc. en vain. J'ai abandonné et éteint mon Mac et je suis rentré chez moi pour la journée. À ma grande surprise, je suis revenu ce matin et tout semblait bien fonctionner!

Je n'ai aucune idée de pourquoi cela a fonctionné, mais si vous êtes bloqué, essayez de redémarrer votre Mac.

javajavajavajavajava
la source
1

Si quelqu'un est bloqué à cause du même problème. Assurez-vous que vous avez correctement lié la base de données (car vous avez peut-être copié le code directement à partir d'un exemple). Mettez
simplement à jour le nom de la base de données dans les méthodes managedObjectModel et persistentStoreCoordinator dans AppDelegate.

nomann
la source
1

J'ai eu le même problème, à savoir

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyModel" withExtension:@"momd"];

renvoyé nil, car aucun fichier .momd n'a été généré.

La raison en était que dans le répertoire de l'application (par exemple MyGreatApp / MyGreatApp.app), xcode avait copié MyModel.xcdatamodeld au lieu de générer le MyModel.momd à partir du fichier MyModel.xcdatamodeld (en utilisant momc).

La solution était de supprimer la référence à MyModel.xcdatamodeld dans le navigateur de projet XCode et de la faire glisser dans le projet à partir du Finder. Après que xcode a réalisé qu'il avait besoin de le compiler en .momd.

Trausti Kristjansson
la source
1

J'ai eu ce problème de nulle part après avoir supprimé l'application générée dans le fichier ~/Library/Application Support/iPhone Simulator. Cela a provoqué l'échec des versions ultérieures dans le simulateur et sur les appareils. N'avait rien changé à voir avec CoreData depuis des lustres, mais cela échouerait avec le Cannot create an NSPersistentStoreCoordinator with a nil model. J'ai essayé quelques choses ci-dessus et rien n'a fonctionné.

Je pouvais voir le dossier momd généré avec le fichier maman à l'intérieur. L'application dans le simulateur pouvait voir les deux, mais elle n'a pas réussi à générer le fichier sqlite.

Ce qui a résolu cela, c'était d'ajouter un attribut à une entité dans mon fichier xcdatamodeld dans Xcode, puis de le supprimer immédiatement. J'espérais que cela permettrait à Xcode de régénérer tout ce qui causait le problème à partir de zéro et cela semblait fonctionner. Je ne sais toujours pas ce qui n'allait pas, mais mon application fonctionne à nouveau dans le simulateur et les appareils.

Alistair McMillan
la source
0

Je viens d'avoir un problème similaire lors de la mise à niveau d'IOS5 vers IOS6. Il s'avère que c'était un problème sensible à la casse avec le nom du modèle.

Je ne sais pas si cela aide quelqu'un.

Troie
la source
0

D'accord, je vais d'abord dire une demi-solution, cela fonctionnera si vous réinstallez l'application (dans le simulateur ou le débogueur). Mais ce n'est pas une vraie solution à coup sûr. Par exemple, si vous mettez à jour votre application, NE le faites PAS ou votre nouvelle version risque de planter car les utilisateurs ne la réinstalleront pas, ils utiliseront le bouton de mise à jour à la place.

Comme je l'ai compris, ce problème se produit principalement lorsque vous modifiez le nom du fichier du modèle de données. La raison pourrait ressembler à ceci:
. Lorsque vous exécutez l'application pour la première fois, elle crée un fichier de modèle de données dans un ensemble d'applications tel que "data_model_1". Cette création ne se produit que pour la première fois.
. Lorsque vous mettez à jour le nom du fichier et exécutez à nouveau l'application, elle ne pourra pas le trouver car il y a toujours un fichier "data_model_1" mais vous lui dites de rechercher "data_model_2". Comment peut-il trouver, il ne l'a pas encore créé et ne le fera pas à moins que vous n'installiez l'application avec un nouveau nom de fichier.

Donc, s'il s'agit de la première version de votre application et que la réinstallation sur un simulateur ou un appareil ne nuit pas à votre projet, allez-y. Sinon, consultez le Guide de gestion des versions et de migration des données du modèle de base de données sur la bibliothèque des développeurs iOS, c'est peut-être ce dont vous avez besoin.

Modifier: si la réinstallation ne fonctionne pas, essayez d'abord de désinstaller, puis de nettoyer le projet, puis de tout fermer, de rouvrir le projet et de construire + exécuter. Cela devrait fonctionner.

Kubilay
la source
0

Si votre projet fonctionne sur le simulateur mais pas sur l'appareil, essayez d'exécuter la version de version sur votre appareil au lieu de la version de débogage.

Sélectionnez votre projet -> Produit -> Modifier le schéma -> Configuration de la construction [DEBUG -> RELEASE]

Maintenant, exécutez à nouveau le projet, cela fonctionnera.

stackr
la source
0

Je suis également confronté à ce problème, mais lorsque je change de ModelName.xcdatamodeldfichier, cela fonctionne. donc je pense que le ModelName.xcdatamodeld fichier n'a pas été ajouté correctement, alors une fois vérifiez et nettoyez l'application et exécutez-la.

Nadella Ravindra
la source
0

Après avoir résolu le problème de dénomination, l'erreur est restée. Ensuite, cela a fonctionné après le redémarrage de Xcode 5. Cela pourrait automatiquement faire la même chose que certaines des suggestions de liens manuelles proposées ici.

EthanP
la source
0

Pour moi, le problème était dû au fait que j'ai copié-collé mon modèle d'un projet sandbox vers mon projet réel. Assurez-vous toujours de générer votre modèle à partir du projet que le modèle est utilisé.

FujiRoyale
la source
0

J'ai rencontré la même erreur lorsque j'ai renommé le .xcdatamodelfichier à partir de xcode et changé le nom renommé dans le délégué d'application partout où c'était nécessaire, mais j'ai toujours la même erreur. Aucune des procédures suggérées n'a fonctionné pour moi.

Ensuite, j'ai ouvert le dossier Finderet j'ai trouvé un fichier supplémentaire .xccurrentversionavec le .xcdatamodelfichier. Je l'ai ouvert dans l' TextEditapplication et j'ai changé ceci:

<dict>
    <key>_XCCurrentVersionName</key>
    <string>Your_Renamed_Model_FileName.xcdatamodel</string>
</dict>

J'utilise ceci avec Xcode 6.4, OSX Yosemite 10.10.1

J'espère que ça aide!

NeverHopeless
la source