CoreData: предупреждение: невозможно загрузить класс с именем

94

Я дублирую существующее приложение телешоу Objective-C в новую версию Swift с использованием Xcode 6.1, и у меня возникли проблемы с CoreData.

Я создал модель из 4 сущностей, создал их подкласс NSManagedObject (в Swift), и для всех файлов установлены правильные цели приложения (для «Компиляция источников»).

Я все еще получаю эту ошибку всякий раз, когда пытаюсь вставить новую сущность:

CoreData: предупреждение: невозможно загрузить класс с именем «Shows» для сущности «Shows». Класс не найден, вместо этого используется NSManagedObject по умолчанию.

Несколько комментариев:

При сохранении в Core Data я использую родительско-дочерний контекст, чтобы разрешить фоновую потоковую передачу. Я делаю это, настраивая ManagedObjectContext, используя:

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

и сохраняя данные с помощью:

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...
})
Джимми
источник

Ответы:

177

Это предупреждение - одна из причуд, с которой нам приходится иметь дело, пока прорабатываются детали реализации Swift. Предупреждение появляется ложно, т.е. ваша установка может работать, даже если вы не выполните шаги, описанные ниже.

В большинстве случаев мне удавалось избавиться от этого, убедившись, что класс правильно установлен в редакторе модели . В отличие от многих других сообщений SOF (включая ответы на этот вопрос), предложение включить имя модуля (например MyApp.Shows) не мне помогло.

Убедитесь, что вы отметили эти три пункта:

1.
Версия, которая работает до Xcode 7 beta 3

До XCode7 b3

Обратите внимание, что я исправил имя вашей сущности на более подходящее единственное число.

Версия, которая работает для Swift 2.0 в Xcode 7.1
(должна работать для Xcode 7 beta 4 и выше)

Вам необходимо удалить текст «Текущий модуль продукта» в модуле!

Из Xcode7 beta 3

2.
Вам также следует следовать частым рекомендациям и включать

@objc(Show)

чуть выше вашего класса.

Примечание . Если вы используете Xcode 7 beta 4 или новее, этот шаг не является обязательным.

3.
Кроме того, убедитесь , чтобы бросить созданный управляемый объект к соответствующему классу, так как по умолчанию будет просто NSManagedObject.

var newShow = NSEntityDescription.insertNewObjectForEntityForName("Show", 
                 inManagedObjectContext: context) as Show
Mundi
источник
3
Спасибо! Я сделал рекомендуемые обновления соглашения об именах, и именно «@objc (Show)», похоже, помогло исправить ошибку «Невозможно загрузить класс ...». Очень признателен!
JimmyJammed
Привет @Mundi. Спасибо вам большое! Вы бы еще помнили, где был источник?
iamdavidlam
1
См., Например, этот вопрос . Там достаточно информации, чтобы понять, что происходит.
Mundi
4
Что интересно, мне пришлось удалить@objc(MyClass)
Дед Мороз
1
@Mundi, возможно, ты снова захочешь обновить свой ответ. См. Обновление ответа хуншана.
Suragch
75

Обновление SWIFT 2 / XCODE 7:

Эта проблема (см. Мой комментарий от 3 апреля к этому ответу) решена в бета-версии Swift 2 и XCode 7 от Apple. Таким образом, вам на самом деле теперь не нужен @objc(myEntity)Swift, как ответил Mundi, или использовать " MyAppName." перед именем вашего класса. Он перестанет работать. Так что удалите их, просто введите Classимя в File и выберите Current Working Moduleкак Module и ура!

Выбор текущего рабочего модуля

Но для тех, кто использует @objc(myEntity)Swift (например, я), вы можете использовать другое решение, которое работает без сбоев.

В правильном классе xcdatamodel в. Он должен выглядеть так:

Установка класса

Ну вот. Module.Classявляется шаблоном для CoreData в Swift и XCode 6. Та же процедура вам понадобится при использовании класса Custom Policy в Model Policy или других материалах CoreData. Примечание: на изображении имя и класс должны быть Car и MyAppName.Car (или любое другое имя вашей сущности). Вот Userопечатка.

хуншан
источник
Проблема с этим решением заключается в том, что автоматически генерируемые классы сущностей больше не будут работать должным образом (будет генерироваться только один класс с именем модуля). См .: Создание подкласса NSManagedObject некорректно .
Милос
Вам необходимо применить решение после создания классов сущностей NSManagedObject. Вероятно, ошибку xcode 6.xx нужно удалить.
khunshan
2
Да, несомненно, это разрешится. Автоматически сгенерированные классы должны быть уже украшены @objc (<имя класса, введенное в инспекторе сущностей>), или, что более вероятно, Apple сделает это ненужным с самого начала.
milos
2
Для людей, все еще читающих это. использование MyAppName.Car у меня не сработало, оно сработало, когда я удалил MyAppName. ' часть. Так что Carкак раз для обоих полей свое дело.
Гидеон
1
ты чемпион !!!! let person = NSEntityDescription.insertNewObject (forEntityName: "Person", в: context) as! Человек
Абхиманью Ратор
36

При использовании Xcode 7 и чисто Swift мне фактически пришлось удалить @objc(MyClass) из моего автоматически сгенерированного NSManagedObjectподкласса (сгенерированного из Editor> Create NSManagedObject Subclass...).

Дед Мороз
источник
4
Вау, спасибо, что опубликовали этот ответ. Я собирался начать биться головой о стену.
Zia
Такая же проблема здесь - отправлена ​​ошибка.
MirekE
У меня тоже сработало. Пришлось его удалить. Странно.
Кент,
По моим экспериментам это выглядит как ложное срабатывание.
Mundi
Мне пришлось удалить его и установить Current Product Module, только тогда он заработал
Олег Шерман
13

В Xcode 7 beta 2 (и я считаю, что 1) в конфигурации модели новый управляемый объект типа Fileустановлен в Module, Current Product Moduleа класс объекта отображается в конфигурации как .File.

Модуль типа управляемого объекта установлен на «Текущий модуль продукта» в Xcode 7

Удаление параметра модуля, чтобы он оставался пустым, или удаление точки, чтобы имя класса в конфигурации было просто Fileэквивалентными действиями, поскольку каждое из них вызывает другое изменение. Сохранение этой конфигурации устранит описанную ошибку.

Модуль управляемого объекта установлен как пустой в Xcode 7

Дункан Бэббидж
источник
9

В Xcode 6.1.1 вам не нужно добавлять атрибут @objc, поскольку базовая сущность является подмножеством класса objc (NSManagedObject) (см. Совместимость типов Swift . В CoreData требуется полное имя Module.Class. Имейте в виду, что модуль name - это то, что задано в Build Settings -> Packaging -> Product Module Name. По умолчанию для него установлено значение $ (PRODUCT_NAME: c99extidentifier), которое будет именем Target .

Джим Малак
источник
Да! Это современный ответ (xcode 6.3.2). Использование правильного названия пакета является ключевым. В моем случае он трансформировался my-productв my_product, и это имело все значение для Core Data.
SimplGy
5

В версии xCode 7 и Swift 2.0 вам не нужно добавлять @objc (NameOfClass), просто измените настройки объекта на вкладке «Показать инспектор модели данных», как показано ниже -

Имя - «Имя вашей организации»

Класс - «Имя вашей сущности»

Модуль - «Текущий модуль продукта»

введите описание изображения здесь

Код для файла класса Entity будет похож (в моем коде Entity is Family) -

import UIKit
import CoreData

class Family: NSManagedObject {

   @NSManaged var member : AnyObject
}

Этот пример отлично работает в моем приложении с xCode 7.0 + swift 2.0

Химаншу Махаджан
источник
3

Не забудьте заменить PRODUCT_MODULE_NAMEна название модуля вашего продукта.

Когда создается новый объект, вам нужно перейти в инспектор модели данных (последняя вкладка) и заменить его PRODUCT_MODULE_NAMEименем вашего модуля, иначе class not foundпри создании постоянного координатора хранилища возникнет ошибка.

Kof
источник
2

Вам также необходимо использовать (по крайней мере, с Xcode 6.3.2) Module.Class при выполнении вашего приведения, например: Предполагая, что ваш модуль (т.е. имя продукта) - Food, а ваш класс - Fruit

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

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

Резюме:

  • Включите имя модуля при определении объекта в редакторе модели данных (Имя: Fruit, Class: Food.Fruit)
  • При доступе к объекту в коде (например, SWIFT) передайте его с помощью Module.class (например, Food.Fruit)
Wizkid
источник
Спасибо, второй момент очень важен. Мне пришлось использовать "Module.Class" при кастинге.
Зойт
1

Изменение имени класса сущности в редакторе модели данных в соответствии с рассматриваемым классом и добавление @objc(NameOfClass)в файл каждого NSManagedObject прямо над объявлением класса решило эту проблему для меня во время модульного тестирования.

user3269767
источник
0

Что сработало для меня (Xcode 7.4, Swift), так это изменение имени класса на <my actual class name>.<entity name> в инспекторе сущностей, поле «Класс».

Мой инициатор подкласса управляемых объектов выглядит так:

    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
отметка
источник
0

Для Xcode 11.5: если свойство Codegen является определением класса, и если вы не получаете предложение для объекта, созданного в xcdatamodel. Попробуйте выйти из Xcode и снова открыть проект. Меня устраивает. Этот ответ предоставляется только в том случае, если вы не получаете предложений, но если ваш файл не создается, попробуйте любой из приведенных выше ответов.

Гульшан Кумар
источник