CoreData: попередження: Не вдається завантажити названий клас


94

Я копіюю існуючу програму Objective-C TV Show на нову версію Swift за допомогою Xcode 6.1 і маю деякі проблеми з CoreData.

Я створив модель з 4 сутностей, створив їх підклас NSManagedObject (у Swift), і всі файли мають відповідні цілі додатків, встановлені (для "Компіляції джерел").

Я все ще отримую цю помилку щоразу, коли намагаюся вставити нову сутність:

CoreData: попередження: Неможливо завантажити клас із назвою "Шоу" для сутності "Шоу". Клас не знайдено, замість нього використано NSManagedObject за замовчуванням.

Кілька коментарів:

Під час збереження в Основні дані я використовую контекстний спосіб батьків-дочірніх, щоб дозволити фонову потокову потокову роботу. Я роблю це, налаштовуючи 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

3
Дякую! Я зробив рекомендовані оновлення конвенції про іменування, і саме "@objc (Показати)", здається, робить трюк у виправленні помилки "Неможливо завантажити клас ...". Цінується!
JimmyJammed

Привіт @Mundi. Дуже дякую! ти все ще пам'ятаєш, де було джерело?
iamdavidlam

1
Дивіться, наприклад, це питання . Там достатньо інформації, щоб зрозуміти, що відбувається.
Mundi


1
@Mundi, можливо, ти захочеш оновити свою відповідь ще раз. Дивіться оновлення відповідей khunshan.
Сурагч

75

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

Ця проблема (див. Також мій коментар до цієї відповіді від 3 квітня) вирішена в бета-версії Swift 2 та XCode 7 від Apple. Отже, вам фактично зараз не потрібна програма @objc(myEntity)Swift, на яку відповів Мунді, або використання " MyAppName." перед назвою вашого класу. Це перестане працювати. Тож вилучіть їх, просто вкажіть Classім’я у файлі та виберіть Current Working Moduleяк Модуль та ура!

Вибір поточного робочого модуля

Але для тих, хто використовує @objc(myEntity)Swift (як я), ви можете замість цього використовувати інше рішення, яке працює безперебійно.

У правильному класі xcdatamodel в. Це повинно виглядати так:

Встановлення класу

Ось вам. Module.Classє шаблоном для CoreData в Swift та XCode 6. Вам також знадобиться та сама процедура, коли ви використовуєте клас Custom Policy у Model Policy або інших матеріалах CoreData. Примітка. На зображенні Ім'я та Клас мають бути Car та MyAppName.Car (або будь-яке інше ім’я Вашої організації). Ось Userпомилка.


Проблема цього рішення полягає в тому, що автоматичне створення класів сутності більше не працюватиме належним чином (генеруватиме лише один клас з іменем модуля). Див .: Створення підкласу NSManagedObject, який не генерується належним чином .
milos

Вам потрібно застосувати рішення після генерації класів сутності NSManagedObject. Можливо, буде видалено помилку xcode 6.xx.
khunshan

2
Так, це, безсумнівно, буде вирішено. Автоматично сформовані класи вже повинні бути прикрашені @objc (<ім'я класу, введене в інспекторі сутності>), або, швидше за все, Apple зробить це непотрібним для початку.
milos

2
Для людей, які все ще читають це. використання ' MyAppName.Car ' не працювало для мене, це спрацювало, коли я видалив ' MyAppName. 'частина. Тож лише Carдля обох полів вдалося зробити свою справу.
Гедеон

1
ти чемпіон !!!! нехай person = NSEntityDescription.insertNewObject (forEntityName: "Person", into: context) як! Person
Abhimanyu Rathore

36

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


4
Вау, дякую за розміщення цієї відповіді. Я вже збирався битися головою об стіну.
Zia

Те саме питання тут - Виправлена ​​помилка.
MirekE

Працював і для мене. Довелося його видалити. Химерний.
Кент,

Згідно з моїми експериментами це виглядає як хибнопозитивний.
Мунді,

Мені довелося його видалити та встановити поточний модуль продукту, лише тоді це спрацювало
Олег Шерман

13

У Xcode 7 beta 2 (і я вважаю 1), у конфігурації моделі новий керований об'єкт типу Fileвстановлюється на Модуль, Current Product Moduleа клас об'єкта відображається в конфігурації як .File.

Модуль керованого типу об'єкта встановлений у "Поточний модуль продукту" в Xcode 7

Видалення налаштування модуля, щоб воно було порожнім, або видалення крапки, щоб назва класу у конфігурації було просто Fileрівнозначними діями, оскільки кожна спричиняє іншу зміну. Збереження цієї конфігурації видалить описану помилку.

Модуль керованого об'єкта встановлено порожнім у Xcode 7


9

У Xcode 6.1.1 вам не потрібно додавати атрибут @objc, оскільки базовий об'єкт є підмножиною класу objc (NSManagedObject) (див. Сумісність типу Swift . У CoreData потрібно вказати повне ім'я Module.Class. Будьте уважні, модуль name - це те, що встановлено в Параметрах збірки -> Упаковка -> Ім'я модуля продукту. За замовчуванням для цього параметра встановлено значення $ (PRODUCT_NAME: c99extidentifier), яке буде іменем цілі .


Так! Це сучасна відповідь (xcode 6.3.2). Ключовим є використання правильної назви набору. У моєму випадку він перетворився my-productна my_product, і це суттєво змінило Core Data.
SimplGy

5

У xCode 7 і версії Swift 2.0 вам не потрібно додавати @objc (NameOfClass), просто змініть параметри сутності на вкладці "Показати інспектор моделі даних", як показано нижче -

Ім'я - "Назва вашої організації"

Клас - "Назва вашої організації"

Модуль - "Поточний модуль продукту"

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

Код для файлу класу Entity матиме такий вигляд (у моєму коді Entity є 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помилки під час створення постійного координатора сховища.


2

Вам також потрібно використовувати (принаймні, з Xcode 6.3.2) модуль. Клас при виконанні акторського складу, наприклад: Припускаючи, що ваш модуль (тобто назва продукту) - це їжа, а ваш клас - фрукти

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

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

Резюме:

  • Включити ім'я модуля при визначенні сутності в редакторі моделі даних (ім'я: фрукти, клас: їжа, фрукти)
  • Під час доступу до сутності в коді (тобто SWIFT), додайте її за допомогою Module.class (наприклад, Food.Fruit)

Дякую, другий пункт дуже важливий. Мені довелося використовувати "Module.Class" під час кастингу.
Зойт


1

Зміна назви класу сутності в редакторі моделі даних на відповідний клас і додавання @objc(NameOfClass)до файлу кожного NSManagedObject прямо над оголошенням класу вирішило цю проблему для мене під час тестування модулів.


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 і знову відкрити свій проект. Це працює для мене. Ця відповідь лише в тому випадку, якщо ви не отримуєте пропозицій, але якщо ваш файл не генерується, спробуйте будь-яку з наведених вище відповідей.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.