No se puede crear un NSPersistentStoreCoordinator con un modelo nulo

96

He tenido mi primer crack en Core Data y obtengo el siguiente error al ejecutar mi código en mi dispositivo, pero funciona bien en el simulador.

* Finalizando la aplicación debido a la excepción no detectada 'NSInvalidArgumentException', motivo: 'No se puede crear un NSPersistentStoreCoordinator con un modelo nulo'

Algunos de mis métodos que pueden estar causando el problema:

    - (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;
    }

EDITAR

Copié y pegué el método managedObjectContext (abajo) de los CoreDataBooks de Apple y ahora funciona ... Aunque no estoy seguro de por qué

- (NSManagedObjectModel *)managedObjectModel {
    if (managedObjectModel != nil) {
        return managedObjectModel;
    }
    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
    return managedObjectModel;
}
Dominic Williams
fuente
Oye, podría ser tan simple como agregar la palabra "Modelo" al primer parámetro URLForResource ... sí, tuve el mismo problema. Luego verifiqué el contenido real de .app en la línea de comando y descubrí que el .momd realmente se estaba creando. Así que intente esto: [[NSBundle mainBundle] URLForResource: @ "RugbyOnTvModel" withExtension: @ "momd"];
Postcodeísmo
NSString *basePath = [paths firstObject];
William Entriken

Respuestas:

157

Recibí exactamente el mismo mensaje de error que en la publicación original. Estuve luchando con esto durante horas. Era esta línea en mi AppDelegate.m.

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

Para cualquiera que busque este mensaje de error y encuentre este hilo ... intente esto primero.

Debe asegurarse de que donde dice [lo mismo con el nombre de xcdatamodeld] .... ¡¡¡eso es !!! Por alguna razón, el mío tenía el nombre de mi proyecto allí y no el nombre del modelo de datos.

Lo cambié y funcionó de inmediato .....

Gracias a Rock & Muller por contribuir ... ¡¡me salvasteis días !!

Gaz.

Gareth Lloyd
fuente
2
Este es el comentario que hizo que me funcionara. El nombre mágico que buscaba mi aplicación era el blahde blah.xcdatamodeld. Gracias internet y stackoverflow.
Acedanger
Tengo "Model.xcdatamodeld", cambiado a "Modelo" como argumento. Pero Xcode se niega a cargarlo, ¡pero este archivo está realmente allí! No sé qué está pasando.
Darmen Amanbayev
Guau. Gracias me golpeó la cabeza por un tiempo.
Sani Elfishawy
¿Qué pasa con el storeURL?
MoralCode
54

primero verificar:

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

Si obtiene un valor nulo, tal vez el problema esté aquí.

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

Intenta cambiar @ "momd" por @ "mom"

D33pN16h7
fuente
1
Tu derecho. Es nulo y, por lo tanto, esta línea está causando el error: `__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];` Sin embargo, cambiar a mamá no parece arreglar nada
Dominic Williams
3
Lo más probable modelURLes que también lo sea nil. La causa más común es un error tipográfico RugbyOnTv. Tenga en cuenta que esto distingue entre mayúsculas y minúsculas.
Rob Napier
1
Cambiar "mamá" por "mamá" también funcionó para mí. Gracias. ¿Pero por qué? ¿Por qué XCode genera código que no funciona? ¿Por qué he encontrado soluciones oscuras como esta en SO para que funcionen las plantillas básicas?
Ruibarbo
10
Habiendo introducido recientemente una segunda versión de mi modelo, tuve que volver a cambiarla a momd. Dado que el contenedor de la versión del modelo tiene una extensión de xdatamodeld, creo que podemos inferir lo que está sucediendo aquí. "momd" es para modelos con más de una versión, mientras que "mom" es para modelos que no tienen versiones.
Gerald
2
Copié el código en un nuevo proyecto [iOS7] palabra por palabra y originalmente estaba disponible para mamá, pero al cambiarlo a mamá lo solucionó. No tengo idea de cómo habría encontrado una solución sin esto, así que gracias :)
Ian Clay
20

Experimenté un problema extraño con Xcode 4.3.2 e iOS 5.

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

devuelve una URL válida pero

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

devuelve un NSManagedObjectModel nulo. Pero después de verificar la documentación , parece que NSManagedObjectModel necesita un archivo donde NAME_OF_THE_MODEL.momd es un directorio que contiene un archivo NAME_OF_THE_MODEL.mom. Cambiar la URL a

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

luego funciona. Sin embargo, parece extraño que Xcode genere código que no funciona por sí mismo ...

xster
fuente
1
Este problema específico se debe a la creación de una versión de modelo adicional y luego al intentar eliminarlo manualmente mientras Xcode está abierto. Esto provoca algún tipo de corrupción. No debe pasar versiones de modelos específicas en el directorio momd.
Mike Weller
genial @MikeWeller, bueno saberlo. ¿Sabes dónde están los metadatos que apuntan al archivo mom en el directorio momd?
xster
No estaba tratando de eliminarlo, pero tuve este problema y la solución publicada funcionó para mí, específicamente, solo agregué una verificación para ver si aún es nula y si lo es, agregué ese código arriba: if (_managedObjectContext == nulo) {NSURL * modelURL = [[NSBundle mainBundle] URLForResource: @ "Model" withExtension: @ "mom" subdirectorio: @ "Model.momd"]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL: modelURL]; }
David van Dugteren
19

Tuve este problema y cambiar "mamás" por "mamá" no hizo nada. Para solucionarlo, tuve que hacer clic con el botón derecho en el archivo xcdatamodelId> mostrar el contenido del paquete y luego eliminar el archivo .xcurrentversion oculto.

PD: Este problema solo comenzó a ocurrir después de que cambié el nombre del archivo del modelo de datos.

JDx
fuente
2
Para todos los que se encuentren con el siguiente problema: managedObjectModel es nulo después de cambiar el nombre del archivo xcdatamodeld: ¡esta respuesta es la mejor! Gracias JDx, tu respuesta me ayudó mucho!
Dumoko
En lugar de eliminarlo, eventualmente puede editarlo para cambiar el nombre de archivo almacenado a la última versión de youl xcdatamodel
furins
13

Otra fuente de este error es que a veces Xcode no incluye el modelo de datos en la compilación.

Compruebe las fases de compilación de su destino y asegúrese de que el archivo * .xcdatamodeld esté incluido en la sección Compilar fuentes.

Dave Wood
fuente
Esto me lo arregló.
Ben Thomas
esto funcionó para mí. ¡Es frustrante y difícil de depurar cuando funciona en Simulator y no en un dispositivo real!
Bishal Ghimire
9

Lo que probablemente sucedió es que su archivo xcdatamodeld del código fuente de Apple se ha convertido en un archivo xcdatamodel (sin el d) y, por lo tanto, no se consideran iguales.

La forma más rápida de solucionar este problema es seleccionar el archivo xcdatamodel en el navegador de su proyecto y en la barra de menú

Editor->Add Model Version...

y agregue una nueva versión de su modelo. Realice todos los cambios en la nueva versión.

Esto funciona en Xcode 5

Louis Cremen
fuente
desafortunadamente, esta opción no existe en Xcode 5 .. ver aquí
abbood
Olvidé mencionar que debe seleccionar el archivo xcdatamodel. Respuesta editada para reflejar el comentario.
Louis Cremen
8

Lo resuelvo agregando el archivo db al archivo Copy Bundle Resources.

Vaya a la raíz de su proyecto >> seleccione su objetivo >> Fases de construcción >> Copiar recursos del paquete. Asegúrese de que su archivo xcdatamodeld se haya agregado aquí.

ingrese la descripción de la imagen aquí

Ninguna de las soluciones publicadas funcionó para mí. Entonces, espero que esta publicación ayude a alguien. Mi aplicación solo falla en versiones de lanzamiento por cierto. Lección aprendida. ¡Siempre pruebe las versiones de lanzamiento!

Por cierto, encontré esta publicación SO la más útil https://stackoverflow.com/a/6708837/951349 .

smileBot
fuente
6

tengo el mismo problema con @Dominic Williams

intente cambiar el nombre del archivo momd a continuación (puede encontrar esto en el managedObjectModelmétodo predeterminado), que es el mismo que el [file name].xcdatamodeldarchivo que creó:

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

Yo tuve el mismo problema. La solución fue una combinación de 2 respuestas:

1) Tuve que agregar el parámetro "subdirectorio" en la llamada URLForResource

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

2) Por una razón que no conozco, el modelo de datos no se incluyó cuando se compiló el proyecto. Tuve que agregarlo manualmente en "Fases de compilación / recursos de compilación".

Con solo una de las soluciones anteriores, mi aplicación no funcionó.

Salvador Ponticelli
fuente
4

La solución al problema del que habla es sencilla. Cambie la extensión del archivo a "mamá" en lugar de "mamá" en la URL del modelo. Hecho.

pfuri
fuente
4

Probé todas las soluciones aquí y ninguna funcionó. Mi problema apareció después de cambiar el nombre del proyecto. Aparentemente, Xcode continúa buscando el archivo momd antiguo en el lugar equivocado durante la compilación.

Para cualquiera que haya probado todas las soluciones anteriores sin éxito, intente verificar la ruta completa de su .xcdatamodeldarchivo. Eso es lo que funcionó para mí.

XCool
fuente
4

Tuve el mismo problema, funcionó bien en iOS6 pero no en iOS5. Así es como lo resolví:

  1. Cree una nueva versión del modelo en xcode. (seleccione .xcdatamodeld, abra el menú Editor y haga clic en "Agregar versión del modelo ...")
  2. Compile y asegúrese de que la nueva versión funcione.
  3. Establezca el anterior como versión actual. ("Actual" en el Inspector de archivos para el .xcdatamodeldmodelo de datos básicos con versiones inferiores)
  4. Eliminar la referencia al .xcdatamodeldarchivo en xcode
  5. Haga clic con el botón derecho en el .xcdatamodeldarchivo en el Finder y seleccione "Mostrar contenido del paquete"
  6. Elimina lo nuevo .xcdatamodelque no quieres
  7. Vuelva a agregar el .xcdatamodelden xcode
  8. Compila y sonríe

(Aquí es donde encontré cómo eliminar una versión de modelo: Cómo eliminar una versión de modelo de datos antigua / no utilizada en Xcode )

Fredrik
fuente
Tack så mycket! Esto fue muy útil.
Michael Dorner
4

Resuelvo el problema sin cambiar ningún código.

Agrego ModelName.xcdatamodeld a través de Archivo-> Agregar archivo en lugar de arrastrar el archivo al Xcode.

 NSString *path=@"ModelName";

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

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

Por mi parte, el problema era que había cambiado el caso de un par de caracteres en el nombre de la base de datos.

Al iniciar un nuevo proyecto, Xcode configura automáticamente todo desde el nombre del proyecto. Si comenzó llamando a su proyecto "Rugbyontv" y luego decidió cambiar a "RugbyOnTV" e hizo una búsqueda y reemplazo, eso lo rompería. (Crédito a Rob por señalar que el nombre distingue entre mayúsculas y minúsculas)

Brian Gerfort
fuente
1

He estado buscando una respuesta durante horas y nada funcionó. Pero de repente encontré este artículo . Entonces, de acuerdo con esto, el problema estaba en configurar el controlador raíz en esta parte de AppDelegate.m:

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

De hecho, debe definir qué controlador raíz delegará su conexión CoreData. Y en mi caso, tenía un TabBarController conectado a otras vistas, por lo que mi controlador raíz de vista dirigida se definió como TabBar y provocó un error. Cambié

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

a

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

y todo funcionó.

kokoko
fuente
1

Sé que esto no resuelve su problema, pero ayer me encontré con este problema que me atormentó durante horas, la solución que @Dominic Williams publicó me dio una ArrayIndexOutOfBoundsException (cualquiera que sea el equivalente de Objective-C).

Todavía no soy muy bueno con Objective-C / Xcode, pero estoy trabajando en una aplicación para iOS que nuestra empresa desarrolló (en su mayoría) externamente. Desafortunadamente, a menudo olvidaban cómo usar un teclado y usaban letras mayúsculas indistintamente o escribían propiedades incorrectamente, pero eran demasiado perezosos para volver atrás y cambiarlo. Habían usado una letra mayúscula en el nombre del proyecto xcode donde no se suponía que debía estar (el nombre de nuestro producto no usa mayúscula) y tuve que volver atrás y cambiar cada aparición de esta letra mayúscula a minúscula ; que incluía el nombre del proyecto, el archivo de datos centrales, cientos de variables, etc.

De todos modos, una vez que hice esto, encontré este error y ninguna solución me lo solucionó. Me había asegurado de que todos los nombres de URL fueran correctos, el proyecto se limpió, la aplicación se desinstaló, el teléfono se reinició, etc. sin éxito. Me di por vencido, apagué mi Mac y me fui a casa por el día. Para mi sorpresa, regresé esta mañana y ¡todo parecía funcionar bien!

No tengo idea de por qué esto funcionó, pero si está atascado, intente reiniciar su Mac.

javajavajavajavajava
fuente
1

Si alguien se queda atascado por el mismo problema. Asegúrese de haber vinculado correctamente la base de datos (ya que podría haber copiado el código directamente de algún ejemplo).
Simplemente actualice el nombre de la base de datos en los métodos managedObjectModel y persistentStoreCoordinator en AppDelegate.

nomann
fuente
1

Tuve el mismo problema, es decir

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

devolvió nulo, porque no se generó ningún archivo .momd.

La razón fue que en el directorio de la aplicación (por ejemplo, MyGreatApp / MyGreatApp.app) xcode había copiado MyModel.xcdatamodeld en lugar de generar MyModel.momd desde el archivo MyModel.xcdatamodeld (usando momc).

La solución fue eliminar la referencia a MyModel.xcdatamodeld dentro del navegador del proyecto XCode y arrastrarlo de nuevo al proyecto desde el buscador. Después de eso, xcode se dio cuenta de que necesitaba compilarlo en un .momd.

Trausti Kristjansson
fuente
1

Tuve este problema de la nada después de eliminar la aplicación generada en ~/Library/Application Support/iPhone Simulator. De alguna manera, esto provocó que las compilaciones posteriores fallaran en el simulador y en los dispositivos. No había cambiado nada que ver con CoreData durante años, pero fallaría con Cannot create an NSPersistentStoreCoordinator with a nil model. Probé algunas cosas anteriores y nada funcionó.

Pude ver la carpeta momd generada con el archivo mom dentro. La aplicación en el simulador pudo ver ambos, pero no pudo generar el archivo sqlite.

Lo que lo resolvió fue agregar un atributo a una entidad en mi archivo xcdatamodeld en Xcode y luego eliminarlo inmediatamente. Esperaba que esto hiciera que Xcode regenerara lo que estaba causando el problema desde cero y parecía funcionar. Todavía no está claro qué estaba realmente mal, pero mi aplicación se está ejecutando en el simulador y los dispositivos nuevamente ahora.

Alistair McMillan
fuente
0

Acabo de tener un problema similar al actualizar de IOS5 a IOS6. Resulta que fue un problema sensible a mayúsculas y minúsculas con el nombre del modelo.

No estoy seguro de si esto ayuda a alguien.

Troya
fuente
0

De acuerdo, primero diré una solución a medias, funcionará si vuelve a instalar la aplicación (en el simulador o dispositivo depurador). Pero esa no es una solución real con seguridad. Por ejemplo, si está actualizando su aplicación, NO haga eso o su nueva versión puede fallar porque los usuarios no la reinstalarán, usarán el botón de actualización en su lugar.

Como entendí, este problema ocurre principalmente cuando cambia el nombre del archivo del modelo de datos. La razón podría ser la siguiente:
. Cuando ejecuta la aplicación por primera vez, está creando un archivo de modelo de datos en un paquete de aplicaciones como "data_model_1". Esta creación ocurre solo por primera vez.
. Cuando actualice el nombre del archivo y ejecute la aplicación nuevamente, no podrá encontrarlo porque todavía hay un archivo "data_model_1" pero le está diciendo que busque "data_model_2". ¿Cómo puede encontrarlo? Aún no lo ha creado y no lo hará a menos que no instale la aplicación con un nuevo nombre de archivo.

Entonces, si esta es la primera versión de su aplicación y la reinstalación en el simulador o dispositivo no daña su proyecto, hágalo. De lo contrario, consulte la Guía de migración de datos y versiones del modelo de datos principal en la biblioteca de desarrolladores de iOS, tal vez sea lo que necesita.

Editar: si la reinstalación no funciona, intente desinstalar primero, luego limpiar el proyecto, luego cerrar todo, volver a abrir el proyecto y construir + ejecutar. Eso debería funcionar.

kubilay
fuente
0

Si su proyecto funciona en el simulador pero no en el dispositivo, intente ejecutar el release-build en su dispositivo en lugar de debug-build.

Seleccione su proyecto -> Producto -> Editar esquema -> Configuración de compilación [DEBUG -> LANZAMIENTO]

Ahora ejecute el proyecto nuevamente, funcionará.

apilador
fuente
0

También estoy enfrentando este problema, pero cuando cambio el ModelName.xcdatamodeldarchivo, está funcionando. así que creo que el ModelName.xcdatamodeld archivo no se agregó correctamente, así que una vez verifique y limpie la aplicación y ejecútela.

Nadella Ravindra
fuente
0

Después de que solucioné el problema del nombre, el error permaneció. Luego funcionó después de reiniciar Xcode 5. Esto podría hacer automáticamente lo mismo que algunas de las sugerencias de enlaces manuales que se ofrecen aquí.

EthanP
fuente
0

Para mí, el problema se debió al hecho de que copié y pegué mi modelo de un proyecto de caja de arena en mi proyecto real. Asegúrese siempre de generar su modelo desde dentro del proyecto en el que se está utilizando el modelo.

FujiRoyale
fuente
0

Me enfrenté a este mismo error cuando cambió el nombre del .xcdatamodelarchivo desde Xcode y cambió el nombre renombrado en delegado de la aplicación donde fuera necesario, pero yo todavía tengo el mismo error. Ninguno de los procedimientos sugeridos funcionó para mí.

Luego abrí la carpeta Findery encontré un archivo adicional .xccurrentversionjunto con el .xcdatamodelarchivo. Lo abrí en la TextEditaplicación y cambié esto:

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

Estoy usando esto con Xcode 6.4, OSX Yosemite 10.10.1

¡Espero que ayude!

Nunca sin esperanza
fuente