CoreData: ostrzeżenie: nie można załadować klasy o nazwie

94

Duplikuję istniejącą aplikację Objective-C TV Show do nowej wersji Swift przy użyciu Xcode 6.1 i mam pewne problemy z CoreData.

Stworzyłem model 4 jednostek, utworzyłem ich podklasę NSManagedObject (w Swift), a wszystkie pliki mają ustawione odpowiednie cele aplikacji (dla „Źródła kompilacji”).

Nadal pojawia się ten błąd za każdym razem, gdy próbuję wstawić nową jednostkę:

CoreData: ostrzeżenie: nie można załadować klasy o nazwie „Programy” dla jednostki „Programy”. Nie znaleziono klasy, zamiast tego użyto domyślnego NSManagedObject.

Kilka uwag:

Podczas zapisywania do danych podstawowych używam sposobu kontekstu rodzic-dziecko, aby umożliwić wątkowanie w tle. Robię to, konfigurując ManagedObjectContext przy użyciu:

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

i zapisując dane za pomocą:

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
źródło

Odpowiedzi:

177

To ostrzeżenie jest jednym z dziwactw, z którymi musimy się uporać podczas dopracowywania szczegółów implementacji Swift. Ostrzeżenie jest fałszywe, tzn. Twoja konfiguracja może działać, nawet jeśli nie wykonasz opisanych poniżej czynności.

W większości przypadków udało mi się go pozbyć, upewniając się, że klasa jest poprawnie ustawiona w edytorze modeli . W przeciwieństwie do wielu innych postów SOF (w tym odpowiedzi na to pytanie), sugestia włączenia nazwy modułu (like MyApp.Shows) nie pomogła mi.

Upewnij się, że sprawdziłeś te trzy elementy:

1.
Wersja, która działa do Xcode 7 beta 3

Aż do XCode7 b3

Zauważ, że poprawiłem nazwę twojego bytu na bardziej odpowiednią liczbę pojedynczą.

Wersja, która działa dla Swift 2.0 w Xcode 7.1
(powinna działać dla Xcode 7 beta 4 i nowszych)

Musisz usunąć tekst „Bieżący moduł produktu” w module!

Z Xcode7 beta 3

2.
Powinieneś także przestrzegać częstego zalecenia dołączania

@objc(Show)

tuż nad twoją klasą.

Uwaga : jeśli używasz Xcode 7 beta 4 lub nowszego, ten krok jest opcjonalny.

3.
Upewnij się również, że utworzony obiekt zarządzany jest rzutowany na odpowiednią klasę, ponieważ domyślna byłaby just NSManagedObject.

var newShow = NSEntityDescription.insertNewObjectForEntityForName("Show", 
                 inManagedObjectContext: context) as Show
Mundi
źródło
3
Dzięki! Zrobiłem zalecane aktualizacje konwencji nazewnictwa i wydaje się, że to „@objc (Show)” rozwiązuje problem z błędem „Unable to load class…”. Bardzo cenione!
JimmyJammed
Cześć @Mundi. Dziękuję bardzo! czy nadal pamiętasz, gdzie było źródło?
iamdavidlam
1
Zobacz np. To pytanie . Jest tam wystarczająco dużo informacji, aby zrozumieć, co się dzieje.
Mundi
4
Co ciekawe, musiałem usunąć @objc(MyClass)
Święty Mikołaj
1
@Mundi, możesz ponownie zaktualizować swoją odpowiedź. Zobacz aktualizację odpowiedzi khunshana.
Suragch
75

Aktualizacja SWIFT 2 / XCODE 7:

Ten problem (zobacz również mój komentarz z 3 kwietnia do tej odpowiedzi) został rozwiązany w wydaniu wersji beta Swift 2 i XCode 7 firmy Apple. Więc właściwie nie potrzebujesz teraz @objc(myEntity)w Swift, jak odpowiedział Mundi lub używając " MyAppName." przed nazwą twojej klasy. Przestanie działać. Więc usuń je, po prostu wpisz Classnazwę w Plik i wybierz Current Working Modulejako moduł i na zdrowie!

Wybór aktualnego modułu roboczego

Ale dla tych, którzy używają @objc(myEntity)w Swift (jak ja), możesz użyć tego innego rozwiązania, które działa płynnie.

W xcdatamodel poprawna klasa w. Powinna wyglądać następująco:

Ustawienie klasy

Proszę bardzo. Module.Classjest wzorcem dla CoreData w Swift i XCode 6. Będziesz również potrzebował tej samej procedury podczas używania klasy Custom Policy w Model Policy lub innych elementach CoreData. Uwaga: na obrazku nazwa i klasa powinny mieć postać Car i MyAppName.Car (lub jakakolwiek inna nazwa Twojej jednostki). Tutaj Userjest literówka.

khunshan
źródło
Problem z tym rozwiązaniem polega na tym, że automatyczne generowanie klas encji nie będzie już działać poprawnie (wygeneruje tylko jedną klasę o nazwie modułu). Zobacz: Tworzenie podklasy NSManagedObject nie generuje się poprawnie .
milos
Musisz zastosować rozwiązanie po wygenerowaniu klas jednostek NSManagedObject. Prawdopodobnie błąd xcode 6.xx do usunięcia.
khunshan
2
Tak, to niewątpliwie zostanie rozwiązane. Klasy generowane automatycznie powinny być już ozdobione @objc (<nazwa klasy wprowadzona w inspektorze encji>) lub, co bardziej prawdopodobne, Apple sprawi, że na początku będzie to niepotrzebne.
milos
2
Dla ludzi, którzy nadal to czytają. korzystanie z „ MyAppName.Car ” nie działało dla mnie, działało, gdy usunąłem „ MyAppName. część. Więc tylko Cardla obu pól załatwiło sprawę.
Gideon
1
ty Champ !!!! niech osoba = NSEntityDescription.insertNewObject (forEntityName: "Person", into: context) as! Osoba
Abhimanyu Rathore
36

Używając Xcode 7 i wyłącznie Swift, musiałem usunąć @objc(MyClass) z mojej automatycznie wygenerowanej NSManagedObjectpodklasy (wygenerowanej z Editor> Create NSManagedObject Subclass...).

Święty Mikołaj
źródło
4
Wow dzięki za opublikowanie tej odpowiedzi. Już miałem zacząć walić głową w ścianę.
Zia
Ten sam problem - zgłosił błąd.
MirekE,
Dla mnie też zadziałało. Musiałem to usunąć. Dziwaczny.
Kent
Według moich eksperymentów wygląda to na fałszywie pozytywny.
Mundi
Musiałem go usunąć i ustawić moduł bieżącego produktu, tylko wtedy zadziałał
Oleg Sherman
13

W Xcode 7 beta 2 (i wierzę 1), w konfiguracji modelu nowy obiekt zarządzany typu Filejest ustawiony na Module, Current Product Modulea klasa obiektu jest wyświetlana w konfiguracji jako .File.

Moduł typu obiektu zarządzanego ustawiony na „Current Product Module” w Xcode 7

Usunięcie ustawienia modułu tak, aby był pusty, lub usunięcie kropki, aby nazwa klasy w konfiguracji była po prostu Fileakcjami równoważnymi, ponieważ każda z nich powoduje inną zmianę. Zapisanie tej konfiguracji usunie opisany błąd.

Moduł zarządzanego obiektu ustawiony jako pusty w Xcode 7

Duncan Babbage
źródło
9

W Xcode 6.1.1 nie musisz dodawać atrybutu @objc, ponieważ jednostka podstawowa jest podzbiorem klasy objc (NSManagedObject) (zobacz Zgodność typu Swift . W CoreData wymagana jest pełna nazwa Module.Class. Pamiętaj, że moduł nazwa jest ustawiona w Ustawienia kompilacji -> Pakowanie -> Nazwa modułu produktu.Domyślnie jest to ustawione na $ (PRODUCT_NAME: c99extidentifier), który będzie nazwą celu .

Jim Malak
źródło
Tak! To jest nowoczesna odpowiedź (xcode 6.3.2). Kluczem jest użycie właściwej nazwy pakietu. W moim przypadku przekształcił się my-productw my_producti to miało znaczenie dla Core Data.
SimplGy
5

W przypadku wersji xCode 7 i Swift 2.0 nie trzeba dodawać @objc (NameOfClass), wystarczy zmienić ustawienia encji na karcie „Pokaż inspektora modelu danych”, jak poniżej -

Nazwa - „Nazwa Twojej jednostki”

Klasa - „Nazwa Twojej jednostki”

Moduł - „Bieżący moduł produktu”

wprowadź opis obrazu tutaj

Kod dla pliku klasy jednostki będzie wyglądał następująco (w moim kodzie Entity is Family) -

import UIKit
import CoreData

class Family: NSManagedObject {

   @NSManaged var member : AnyObject
}

Ten przykład działa dobrze w mojej aplikacji z xCode 7.0 + Swift 2.0

Himanshu Mahajan
źródło
3

Nie zapomnij zastąpić PRODUCT_MODULE_NAMEnazwą modułu produktu.

Po utworzeniu nowej encji musisz przejść do Inspektora modelu danych (ostatnia karta) i zastąpić PRODUCT_MODULE_NAMEnazwą swojego modułu, w przeciwnym razie spowoduje to class not foundbłąd podczas tworzenia stałego koordynatora magazynu.

Kof
źródło
2

Musisz także użyć (przynajmniej z Xcode 6.3.2) Module.Class podczas obsady, na przykład: Zakładając, że twój moduł (tj. Nazwa produktu) to Food, a twoja klasa to Fruit

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

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

Podsumować:

  • Uwzględnij nazwę modułu podczas definiowania jednostki w edytorze modelu danych (nazwa: owoc, klasa: żywność.owoc)
  • Podczas uzyskiwania dostępu do encji w kodzie (tj.SWIFT), prześlij ją za pomocą Module.class (np. Food.Fruit)
Wizkid
źródło
Dziękuję, druga kwestia jest bardzo ważna. Podczas przesyłania musiałem użyć „Module.Class”.
Zoyt
1

Zmiana nazwy klasy jednostki w edytorze modelu danych tak, aby odpowiadała danej klasie i dodanie @objc(NameOfClass)do pliku każdego NSManagedObject tuż nad deklaracją klasy rozwiązało ten problem podczas testów jednostkowych.

user3269767
źródło
0

To, co zadziałało dla mnie (Xcode 7.4, Swift), to zmiana nazwy klasy na <my actual class name>.<entity name> w Inspektorze jednostek, w polu „Klasa”.

Mój inicjator podklasy obiektu zarządzanego wygląda następująco:

    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
znak
źródło
0

Dla Xcode 11.5: jeśli właściwość Codegen to Definicja klasy i jeśli nie otrzymujesz sugestii dla jednostki utworzonej w xcdatamodel. Spróbuj zamknąć Xcode i ponownie otworzyć projekt. Mi to pasuje. Ta odpowiedź jest tylko wtedy, gdy nie otrzymujesz sugestii, ale jeśli plik nie zostanie wygenerowany, wypróbuj dowolną z powyższych odpowiedzi.

Gulshan Kumar
źródło