CoreData: aviso: Não é possível carregar a classe nomeada

94

Estou duplicando um aplicativo Objective-C TV Show existente para uma nova versão do Swift usando o Xcode 6.1 e estou tendo alguns problemas com CoreData.

Eu criei um modelo de 4 entidades, criei sua subclasse NSManagedObject (em Swift) e todos os arquivos têm os destinos de aplicativo adequados definidos (para 'Compile Sources').

Ainda recebo este erro sempre que tento inserir uma nova entidade:

CoreData: aviso: Incapaz de carregar a classe chamada 'Shows' para a entidade 'Shows'. Classe não encontrada, usando o NSManagedObject padrão.

Alguns comentários:

Ao salvar no Core Data, eu uso a forma de contexto pai-filho para permitir threading em segundo plano. Eu faço isso configurando o ManagedObjectContext usando:

lazy var managedObjectContext: NSManagedObjectContext? = {
  // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
  let coordinator = self.persistentStoreCoordinator
  if coordinator == nil {
    return nil
  }
  var managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.MainQueueConcurrencyType)
  managedObjectContext.persistentStoreCoordinator = coordinator
  return managedObjectContext
}()

e salvando dados usando:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
  var context = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
  context.parentContext = self.managedObjectContext!
  ...rest of core data saving code here...
})
JimmyJammed
fonte

Respostas:

177

Este aviso é uma das peculiaridades com as quais temos que lidar enquanto os detalhes da implementação do Swift estão sendo resolvidos. O aviso ocorre espúrio, ou seja, sua configuração pode funcionar mesmo se você não seguir as etapas descritas abaixo.

Consegui me livrar dele na maioria dos casos , certificando-me de que a classe está configurada corretamente no editor de modelo . Ao contrário de muitos outros posts SOF (incluindo respostas a esta pergunta), a sugestão de incluir o nome do módulo (como MyApp.Shows) não me ajudou.

Certifique-se de verificar estes três itens:

1.
Versão que funciona até o Xcode 7 beta 3

Até XCode7 b3

Observe que eu corrigi o nome da sua entidade para o singular mais apropriado.

Versão que funciona para Swift 2.0 no Xcode 7.1
(deve funcionar para Xcode 7 beta 4 e superior)

Você precisa excluir o texto "Módulo de produto atual" no Módulo!

Do Xcode7 beta 3

2.
Você também deve seguir as recomendações frequentes para incluir

@objc(Show)

logo acima de sua classe.

Nota : Se você estiver usando o Xcode 7 beta 4 ou posterior, esta etapa é opcional.

3.
Certifique-se também de lançar o objeto gerenciado criado para a classe adequada, pois o padrão seria justo NSManagedObject.

var newShow = NSEntityDescription.insertNewObjectForEntityForName("Show", 
                 inManagedObjectContext: context) as Show
Mundi
fonte
3
Obrigado! Eu fiz as atualizações de convenção de nomenclatura recomendadas e foi o '@objc (Mostrar)' que parece resolver o erro 'Não foi possível carregar a classe ...'. Muito apreciado!
JimmyJammed
Olá @Mundi. Muito obrigado! você ainda se lembraria de onde estava a fonte?
iamdavidlam
1
Veja, por exemplo, esta questão . Há informações suficientes para entender o que está acontecendo.
Mundi
4
Curiosamente, eu tive que remover @objc(MyClass)
Papai Noel de
1
@Mundi, você pode querer atualizar sua resposta novamente. Veja a atualização de resposta de khunshan.
Suragch
75

Atualização SWIFT 2 / XCODE 7:

Esse problema (veja meu comentário de 3 de abril sobre esta resposta também) foi resolvido no lançamento beta do Swift 2 e XCode 7 pela Apple. Portanto, agora você não precisa @objc(myEntity)usar o Swift como respondido por Mundi ou usar " MyAppName." antes do nome da sua classe. Vai parar de funcionar. Portanto remova estes, basta colocar o Classnome em Arquivo e selecionar Current Working Modulecomo Módulo e felicidades!

Selecionando o módulo de trabalho atual

Mas para aqueles que usam o @objc(myEntity)Swift (como eu), você pode usar esta outra solução, que funciona sem problemas.

Na classe correta xcdatamodel em. Deve ser assim:

Configurando a aula

Aqui está. Module.Classé o padrão para CoreData em Swift e XCode 6. Você também precisará do mesmo procedimento ao usar a classe de Política Personalizada na Política de Modelo ou outras coisas CoreData. Uma nota: Na imagem, o nome e a classe devem ser Car e MyAppName.Car (ou qualquer que seja o nome da sua entidade). Aqui Userestá um erro de digitação.

khunshan
fonte
O problema com essa solução é que as classes de entidade geradas automaticamente não funcionarão mais corretamente (gerará apenas uma classe com o nome do módulo). Consulte: Criar subclasse NSManagedObject não gerando corretamente .
milos,
Você precisa aplicar a solução após gerar classes de entidade NSManagedObject. Provavelmente um bug do xcode 6.xx a ser removido.
khunshan,
2
Sim, isso sem dúvida será resolvido. As classes geradas automaticamente já devem estar adornadas com @objc (<nome da classe conforme inserido no inspetor de entidade>) ou, mais provavelmente, a Apple tornará isso desnecessário para começar.
milos,
2
Para as pessoas que ainda estão lendo isso. usar ' MyAppName.Car ' não funcionou para mim, funcionou quando removi o ' MyAppName. 'parte. Portanto, apenas Carpara os dois campos funcionou.
Gideon
1
você campeão !!!! let person = NSEntityDescription.insertNewObject (forEntityName: "Person", into: context) as! Pessoa
Abhimanyu Rathore
36

Ao usar o Xcode 7 e puramente Swift, eu realmente tive que remover @objc(MyClass) da minha NSManagedObjectsubclasse gerada automaticamente (gerada a partir de Editor> Create NSManagedObject Subclass...).

Papai Noel
fonte
4
Uau, obrigado por postar esta resposta. Eu estava prestes a começar a bater minha cabeça contra a parede.
Zia
Mesmo problema aqui - Enviado um bug.
MirekE de
Funcionou para mim também. Tive que removê-lo. Bizarro.
Kent
De acordo com minhas experiências, parece um falso positivo.
Mundi
Tive que removê-lo e definir o Módulo de produto atual, só então funcionou
Oleg Sherman
13

No Xcode 7 beta 2 (e acredito que 1), na configuração do modelo, um novo objeto gerenciado do tipo Fileé definido para o Módulo Current Product Modulee a classe do objeto é mostrada na configuração como .File.

Módulo do tipo de objeto gerenciado definido como "Módulo de produto atual" no Xcode 7

Excluir a configuração do módulo para que fique em branco ou remover o ponto final para que o nome da classe na configuração seja apenas Fileações equivalentes, pois cada uma causa a outra alteração. Salvar esta configuração removerá o erro descrito.

Módulo de objeto gerenciado definido como em branco no Xcode 7

Duncan Babbage
fonte
9

No Xcode 6.1.1, você não precisa adicionar o atributo @objc, pois a entidade base é um subconjunto de uma classe objc (NSManagedObject) (consulte Compatibilidade de tipo Swift . Em CoreData, o nome completo do Module.Class é obrigatório. Esteja ciente do módulo name é o que é definido em Build Settings -> Packaging -> Product Module Name. Por padrão, isso é definido como $ (PRODUCT_NAME: c99extidentifier), que será o nome do destino .

Jim Malak
fonte
Sim! Esta é a resposta moderna (xcode 6.3.2). Usar o nome do pacote correto é fundamental. No meu caso, ele se transformou my-productem my_product, e isso fez toda a diferença para o Core Data.
SimplGy
5

Com o xCode 7 e a versão Swift 2.0, você não precisa adicionar @objc (NameOfClass), apenas altere as configurações de entidade na guia "Mostrar o Inspetor de modelo de dados" como abaixo -

Nome - "Nome de sua entidade"

Classe - "Seu nome de entidade"

Módulo - "Módulo de produto atual"

insira a descrição da imagem aqui

Código para arquivo de classe Entity será como (no meu código Entity is Family) -

import UIKit
import CoreData

class Family: NSManagedObject {

   @NSManaged var member : AnyObject
}

Este exemplo está funcionando bem em meu aplicativo com xCode 7.0 + swift 2.0

Himanshu Mahajan
fonte
3

Não se esqueça de substituir PRODUCT_MODULE_NAME pelo nome do módulo do seu produto.

Quando uma nova entidade é criada, você precisa ir para o Data Model Inspector (última guia) e substituir PRODUCT_MODULE_NAMEpelo nome do seu módulo, ou resultará em um class not founderro ao criar o coordenador de armazenamento persistente.

Kof
fonte
2

Você também precisa usar (pelo menos com o Xcode 6.3.2) Module.Class ao realizar seu elenco, por exemplo: Assumindo que seu módulo (ou seja, nome do produto) é Food e sua classe é Fruit

let myEntity =  NSEntityDescription.entityForName("Fruit", inManagedObjectContext: managedContext)

let fruit = NSManagedObject(entity: myEntity!, insertIntoManagedObjectContext:managedContext) as! Food.Fruit

Recapitular:

  • Incluir o nome do módulo ao definir a entidade no Editor de Modelo de Dados (Nome: Frutas, Classe: Alimentos.Frutas)
  • Ao acessar a entidade em código (isto é, SWIFT), lance-a com Module.class (por exemplo, Food.Fruit)
Wizkid
fonte
Obrigado, o segundo ponto é muito importante. Tive que usar "Module.Class" ao lançá-lo.
Zoyt
1

Alterar o nome da classe de entidade no editor de modelo de dados para corresponder à classe em questão e adicionar @objc(NameOfClass)ao arquivo de cada NSManagedObject logo acima da declaração da classe resolveu esse problema para mim durante o teste de unidade.

user3269767
fonte
0

O que funcionou para mim (Xcode 7.4, Swift) foi mudar o nome da classe para <my actual class name>.<entity name> no inspetor de entidade, caixa 'Classe'.

Meu iniciador da subclasse de objeto gerenciado se parece com isto:

    convenience init(<properties to init>) {
    let entityDescr = NSEntityDescription.entityForName("<entity class name>", inManagedObjectContext: <managed context>)
    self.init(entity: entityDescr!, insertIntoManagedObjectContext: <managed context>)}
    //init properties here
marca
fonte
0

Para Xcode 11.5: se a propriedade Codegen for a classe Definição, e se você não estiver recebendo uma sugestão para a entidade que criou no xcdatamodel. Tente sair do Xcode e reabrir seu projeto novamente. Funciona para mim. Esta resposta é apenas se você não estiver recebendo sugestões, mas se o seu arquivo não for gerado, tente qualquer resposta acima.

Gulshan Kumar
fonte