Não é possível criar um NSPersistentStoreCoordinator com um modelo nulo

96

Estou tendo meu primeiro crack no Core Data e estou recebendo o seguinte erro ao executar meu código no meu dispositivo, mas funciona bem no simulador ..

* Encerrando aplicativo devido à exceção não detectada 'NSInvalidArgumentException', motivo: 'Não é possível criar um NSPersistentStoreCoordinator com um modelo nulo'

Alguns dos meus métodos que podem estar causando o 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

Copiei e colei o método managedObjectContext (abaixo) dos CoreDataBooks da Apple e agora funciona ... Não tenho certeza do porquê, embora

- (NSManagedObjectModel *)managedObjectModel {
    if (managedObjectModel != nil) {
        return managedObjectModel;
    }
    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
    return managedObjectModel;
}
Dominic Williams
fonte
Ei, poderia ser tão simples quanto anexar a palavra "Model" ao primeiro parâmetro URLForResource ... sim, eu tive o mesmo problema. Em seguida, verifiquei o conteúdo real do .app na linha de comando e descobri que o .momd estava realmente sendo criado. Então tente isto: [[NSBundle mainBundle] URLForResource: @ "RugbyOnTvModel" withExtension: @ "momd"];
PostCodeism
NSString *basePath = [paths firstObject];
William Entriken,

Respostas:

157

Recebi exatamente a mesma mensagem de erro da postagem original. Fiquei lutando com isso por horas. Foi esta linha no meu AppDelegate.m.

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

Para qualquer um que esteja pesquisando esta mensagem de erro e encontrando este tópico ... tente isto primeiro.

Você deve ter certeza de que onde diz [mesmo com o nome de xcdatamodeld] .... que está !!! Por algum motivo, o meu tinha o nome do meu projeto e não o nome do modelo de dados.

Alterei e funcionou imediatamente ...

Obrigado a Rock & Muller por contribuir ... você me salvou dias !!

Gaz.

Gareth Lloyd
fonte
2
Este é o comentário que fez funcionar para mim. O nome mágico que meu aplicativo estava procurando era blahde blah.xcdatamodeld. Obrigado internet e stackoverflow.
acedanger
Eu tenho "Model.xcdatamodeld", alterado para "Model" como argumento. Mas o Xcode se recusa a carregá-lo, mas este arquivo está realmente lá! Eu não sei o que está acontecendo.
Darmen Amanbayev
Uau. Obrigado estava batendo na minha cabeça por um tempo.
Sani Elfishawy
e quanto ao storeURL um?
MoralCode
54

primeiro verifique:

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

Se você obtiver um valor nulo, talvez o problema esteja aqui

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

Então, tente mudar @ "momd" por @ "mom"

D33pN16h7
fonte
1
Você está certo. É nulo e esta linha está causando o erro: `__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];` Mudar para mãe não parece corrigir nada
Dominic Williams
3
Provavelmente modelURLtambém nil. A causa mais comum é um erro de digitação RugbyOnTv. Observe que isso diferencia maiúsculas de minúsculas.
Rob Napier,
1
Mudar de "mãe" para "mãe" funcionou para mim também. Obrigado. Mas por que? Por que o XCode está gerando código que não funciona? Por que eu encontrei correções obscuras como essa no SO para fazer os modelos básicos funcionarem?
Ruibarbo
10
Tendo introduzido recentemente uma segunda versão do meu modelo, tive que alterá-lo de volta para o momd. Dado que o contêiner de versão do modelo tem uma extensão xdatamodeld, acho que podemos inferir o que está acontecendo aqui. "momd" é para modelos com mais de uma versão, enquanto "mom" é para modelos que não têm versão.
Gerald
2
Copiei o código para um novo projeto [iOS7] literalmente e ele foi originalmente momd, mas mudar para mom corrigiu isso. Não tenho ideia de como eu teria encontrado uma solução sem isso, então obrigado :)
Ian Clay
20

Tive um problema estranho com o Xcode 4.3.2 e iOS 5.

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

retorna um URL válido, mas

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

retorna um NSManagedObjectModel nulo. Mas depois de verificar a documentação , parece que NSManagedObjectModel precisa de um arquivo onde NAME_OF_THE_MODEL.momd é um diretório que contém um arquivo NAME_OF_THE_MODEL.mom. Alterando o URL para

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

então funciona. Mas parece estranho que o Xcode gere um código que não funciona sozinho ...

xster
fonte
1
Esse problema específico é causado pela criação de uma versão de modelo extra e, em seguida, pela tentativa de excluí-la manualmente enquanto o Xcode está aberto. Isso causa algum tipo de corrupção. Você não deve passar versões de modelos específicos no diretório momd.
Mike Weller
legal @MikeWeller, bom saber. Você sabe onde estão os metadados que apontam para o arquivo mom no diretório momd?
xster
Eu não estava tentando excluí-lo, mas tive esse problema e a solução postada funcionou para mim, especificamente, apenas adicionei uma verificação para ver se ainda é nulo e se for, adicionei o código acima: if (_managedObjectContext == nil) {NSURL * modelURL = [[NSBundle mainBundle] URLForResource: @ "Model" withExtension: @ subdiretório "mom": @ "Model.momd"]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL: modelURL]; }
David van Dugteren
19

Eu tive esse problema e mudar "mães" para "mães" não adiantou nada. Para consertar, tive que clicar com o botão direito do mouse no arquivo xcdatamodelId> mostrar o conteúdo do pacote e excluir o arquivo .xcurrentversion oculto.

PS: Esse problema só começou a acontecer depois que alterei o nome do arquivo do modelo de dados.

JDx
fonte
2
Para todos que encontram o seguinte problema: managedObjectModel sendo nulo após renomear o arquivo xcdatamodeld: esta resposta é a melhor! Obrigado JDx, sua resposta me ajudou muito!
Dumoko de
Em vez de excluí-lo você pode, eventualmente, editá-lo, a fim de mudar o nome do arquivo armazenado para a última versão do xcdatamodel youl
Furins
13

Outra fonte desse erro é que às vezes o Xcode não inclui o modelo de dados na construção.

Verifique as fases de construção de seu destino e certifique-se de que o arquivo * .xcdatamodeld esteja incluído na seção Compile Sources.

Dave Wood
fonte
Isso consertou para mim.
Ben Thomas
isso funcionou para mim. É frustrante e difícil de depurar quando funciona no Simulador e não em um dispositivo real!
Bishal Ghimire
9

O que provavelmente aconteceu é que seu arquivo xcdatamodeld do código-fonte da Apple se transformou em um arquivo xcdatamodelo (sem ad) e, portanto, eles não são considerados iguais.

A maneira mais rápida de corrigir isso é selecionar o arquivo xcdatamodel no navegador do seu projeto e na barra de menu

Editor->Add Model Version...

e adicione uma nova versão do seu modelo. Faça todas as alterações na nova versão.

Isso funciona no Xcode 5

Louis Cremen
fonte
infelizmente, esta opção não existe no Xcode 5 .. veja aqui
abbood
Esqueci de mencionar que você precisa selecionar o arquivo xcdatamodel. Resposta editada para refletir o comentário.
Louis Cremen
8

Eu resolvo isso adicionando o arquivo db ao Copy Bundle Resources .

Vá para a raiz do seu projeto >> selecione o seu destino >> Construir fases >> Copiar recursos do pacote. Certifique-se de que seu arquivo xcdatamodeld foi adicionado aqui.

insira a descrição da imagem aqui

Nenhuma das soluções postadas funcionou para mim. Então, espero que este post ajude alguém por aí. Meu aplicativo só trava em compilações de lançamento. Lição aprendida. Sempre teste as compilações de lançamento!

BTW, achei este post de SO o mais útil https://stackoverflow.com/a/6708837/951349 .

smileBot
fonte
6

eu tenho o mesmo problema com @Dominic Williams

tente alterar o nome do arquivo momd abaixo (você pode encontrar isso no managedObjectModelmétodo padrão), que é igual ao [file name].xcdatamodeldarquivo que você criou:

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

Eu tive o mesmo problema. A solução foi uma mistura de 2 respostas:

1) Tive que adicionar o parâmetro "subdiretório" na chamada URLForResource

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

2) Por um motivo que não sei, o modelo de dados não foi incluído quando o projeto foi compilado. Tive que adicioná-lo manualmente em "Build Phases / Compile resources".

Com apenas uma das soluções acima, meu aplicativo não funcionou.

Salvador Ponticelli
fonte
4

A solução para o problema de que você fala é simples. Altere a extensão do arquivo para "mom" em vez de "momd" no URL do modelo. Feito.

pfuri
fonte
4

Tentei todas as soluções aqui e nenhuma funcionou. Meu problema apareceu depois de renomear o projeto. Aparentemente, o Xcode continua procurando pelo arquivo momd antigo no lugar errado durante a compilação.

Para qualquer pessoa que tentou todas as soluções acima sem sucesso, tente verificar o caminho completo do seu .xcdatamodeldarquivo. Isso é o que funcionou para mim.

XCool
fonte
4

Eu tive o mesmo problema, funcionou bem no iOS6, mas não no iOS5. Foi assim que resolvi:

  1. Crie uma nova versão do modelo no xcode. (selecione .xcdatamodeld, abra o menu Editor e clique em "Adicionar versão do modelo ...")
  2. Compile e verifique se a nova versão funciona.
  3. Defina o antigo como a versão atual. ("Atual" no Inspetor de Arquivos para o .xcdatamodeldModelo de Dados Principal com Versão)
  4. Remova a referência ao .xcdatamodeldarquivo no xcode
  5. Clique com o botão direito no .xcdatamodeldarquivo no Finder e escolha "Mostrar conteúdo do pacote"
  6. Exclua o novo .xcdatamodelque você não quer
  7. Adicionar novamente o .xcdatamodeldxcode
  8. Compile e sorria

(Aqui é onde descobri como excluir uma versão de modelo: como excluir uma versão de modelo de dados antiga / não usada no Xcode )

Fredrik
fonte
Tack så mycket! Isso foi muito útil.
Michael Dorner
4

Resolvo o problema sem alterar nenhum código.

Eu adiciono o ModelName.xcdatamodeld através de File-> Add File em vez de arrastar o arquivo para o Xcode.

 NSString *path=@"ModelName";

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

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

Do meu lado, o problema é que eu alterei a capitalização de alguns caracteres no nome do banco de dados.

Ao iniciar um novo projeto, o Xcode configura tudo automaticamente a partir do nome do projeto. Se você começou chamando seu projeto de "Rugbyontv" e depois decidiu mudar para "RugbyOnTV" e fez uma busca e substituição, isso o quebraria. (Agradecemos a Rob por apontar que o nome diferencia maiúsculas de minúsculas)

Brian Gerfort
fonte
1

Estou procurando uma resposta há horas e nada funcionou. Mas, de repente, encontrei este artigo . Portanto, de acordo com isso, o problema estava em definir o controlador raiz nesta parte do AppDelegate.m:

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

Na verdade, você deve definir qual controlador raiz delegará sua conexão CoreData. E no meu caso eu tinha um TabBarController conectado a outras visualizações, então meu controlador de raiz de visualização tarada foi definido como TabBar e causou um erro. eu mudei

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

para

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

e tudo funcionou.

Kokoko
fonte
1

Eu sei que isso não resolve o seu problema, mas me deparei com esse problema ontem que me atormentou por horas, a solução que @Dominic Williams postou me deu uma ArrayIndexOutOfBoundsException (qualquer que seja o equivalente Objective-C).

Não sou muito bom com Objective-C / Xcode ainda, mas estou trabalhando em um aplicativo iOS que nossa empresa desenvolveu externamente. Infelizmente, eles muitas vezes esqueciam como usar um teclado e usavam letras maiúsculas alternadamente ou soletravam propriedades incorretamente, mas eram preguiçosos para voltar e alterá-lo. Eles usaram uma letra maiúscula no nome do projeto xcode onde não deveria estar (nosso nome de produto não usa maiúscula) e eu tive que voltar e mudar cada ocorrência desta letra maiúscula para minúscula ; que incluiu o nome do projeto, arquivo de dados principais, centenas de variáveis, etc.

De qualquer forma, depois de fazer isso, encontrei esse erro e nenhuma solução foi consertar para mim. Eu me certifiquei de que todos os nomes de URL estavam corretos, projeto limpo, aplicativo desinstalado, telefone reiniciado, etc, sem sucesso. Desisti e desliguei o meu Mac e foi para casa para o dia. Para minha surpresa, voltei esta manhã e tudo parecia funcionar bem!

Não tenho ideia de por que isso funcionou, mas se você travou, tente reiniciar o Mac.

javajavajavajavajava
fonte
1

Se alguém está preso por causa do mesmo problema. Certifique-se de ter vinculado o banco de dados corretamente (já que você pode ter copiado o código diretamente de algum exemplo).
Basta atualizar o nome do banco de dados nos métodos managedObjectModel e persistentStoreCoordinator no AppDelegate.

nomann
fonte
1

Eu tive o mesmo problema, ou seja

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

retornou nulo, porque nenhum arquivo .momd foi gerado.

O motivo foi que no diretório do aplicativo (por exemplo, MyGreatApp / MyGreatApp.app), o xcode copiou o MyModel.xcdatamodeld em vez de gerar o MyModel.momd do arquivo MyModel.xcdatamodeld (usando momc).

A solução foi excluir a referência a MyModel.xcdatamodeld dentro do navegador do projeto XCode e arrastá-la de volta para o projeto a partir do localizador. Depois que o xcode percebeu que precisava compilá-lo em um .momd.

Trausti Kristjansson
fonte
1

Tive esse problema do nada depois de excluir o aplicativo gerado no ~/Library/Application Support/iPhone Simulator. De alguma forma, isso fez com que as compilações subsequentes falhassem no simulador e nos dispositivos. Não mudou nada a ver com CoreData por muito tempo, mas iria falhar com oCannot create an NSPersistentStoreCoordinator with a nil model . Tentei algumas coisas acima e nada funcionou.

Pude ver a pasta momd gerada com o arquivo mom dentro. O aplicativo no simulador podia ver ambos, mas falhou ao gerar o arquivo sqlite.

O que resolveu foi adicionar um atributo a uma entidade no meu arquivo xcdatamodeld no Xcode e, em seguida, excluí-lo imediatamente. Eu esperava que isso fizesse o Xcode regenerar tudo o que estava causando o problema do zero e parecia funcionar. Ainda não está claro o que realmente estava errado, mas meu aplicativo está sendo executado no simulador e nos dispositivos novamente agora.

Alistair McMillan
fonte
0

Acabei de ter um problema semelhante ao atualizar do IOS5 para o IOS6. Acontece que era um problema de distinção entre maiúsculas e minúsculas com o nome do modelo.

Não tenho certeza se isso ajuda alguém.

Troy
fonte
0

Ok, vou contar uma meia solução primeiro, vai funcionar se você reinstalar o aplicativo (no simulador ou dispositivo de depuração). Mas essa não é uma solução real com certeza. Por exemplo, se você estiver atualizando seu aplicativo, NÃO faça isso ou sua nova versão pode travar porque os usuários não a reinstalarão; em vez disso, eles usarão o botão de atualização.

Pelo que entendi, esse problema ocorre principalmente quando você altera o nome do arquivo do modelo de dados. A razão pode ser assim:
. Quando você executa o aplicativo pela primeira vez, ele está criando um arquivo de modelo de dados no pacote de aplicativos como "data_model_1". Esta criação acontece apenas pela primeira vez.
. Quando você atualiza o nome do arquivo e executa o aplicativo novamente, ele não será capaz de encontrar porque ainda há o arquivo "data_model_1", mas você está dizendo a ele para procurar "data_model_2". Como ele pode encontrar, ele ainda não o criou e não o fará, a menos que você não instale o aplicativo com o novo nome de arquivo.

Portanto, se esta é a primeira versão do seu aplicativo e a reinstalação no simulador ou dispositivo não prejudica o seu projeto, vá em frente. Caso contrário, consulte o Guia de controle de versão e migração de dados do modelo de dados principal na biblioteca de desenvolvedores iOS, talvez seja o que você precisa.

Editar: se a reinstalação não funcionar, tente desinstalar primeiro, depois limpar o projeto, depois fechar tudo, reabrir o projeto e construir + executar. Isso deve funcionar.

Kubilay
fonte
0

Se o seu projeto funciona no simulador, mas não no dispositivo, tente executar o build de lançamento no seu dispositivo em vez do build de depuração.

Selecione seu projeto -> Produto -> Editar Esquema -> Configuração de Compilação [DEBUG -> RELEASE]

Agora execute o projeto novamente, ele funcionará.

stackr
fonte
0

Também estou enfrentando esse problema, mas quando mudo o ModelName.xcdatamodeldarquivo, ele está funcionando. então eu acho que o ModelName.xcdatamodeld arquivo não foi adicionado corretamente, então uma vez verifique e limpe o aplicativo e execute-o.

Nadella Ravindra
fonte
0

Depois de corrigir o problema de nomenclatura, o erro permaneceu. Então funcionou depois de reiniciar o Xcode 5. Isso pode fazer automaticamente a mesma coisa que algumas das sugestões manuais de links oferecidas aqui.

EthanP
fonte
0

Para mim, o problema foi devido ao fato de que copiei e colei meu modelo de um projeto de sandbox no meu projeto real. Sempre certifique-se de gerar seu modelo de dentro do projeto em que o modelo está sendo usado.

FujiRoyale
fonte
0

Eu enfrentei esse mesmo erro quando renomeei o .xcdatamodelarquivo de xcode e alterei o nome renomeado no delegado do aplicativo sempre que necessário, mas ainda recebo o mesmo erro. Nenhum dos procedimentos sugeridos funcionou para mim.

Em seguida, abri a pasta Findere encontrei um arquivo adicional .xccurrentversionjunto com o .xcdatamodelarquivo. Eu abri no TextEditaplicativo e mudei isso:

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

Estou usando isso com o Xcode 6.4, OSX Yosemite 10.10.1

Espero que ajude!

NeverHopeless
fonte