Tak dapat menemukan subkelas tertentu dari NSManagedObject

137

Saya sedang mengembangkan aplikasi dengan Core Data. Ketika saya membuat sebuah instance menggunakan:

let entity = NSEntityDescription.entityForName("User", inManagedObjectContext: appDelegate.managedObjectContext)
let user = User(entity: entity, insertIntoManagedObjectContext: appDelegate.managedObjectContext)

Saya mendapat peringatan di log:

CoreData: warning: Unable to load class named 'User' for entity 'User'.  Class not found, using default NSManagedObject instead.

Bagaimana saya bisa memperbaikinya?

Dan pertanyaan lain, bagaimana saya bisa mendefinisikan metode contoh di subclass NSManagedObject?

Edit:

Saya telah menentukan kelas entitas seperti pada tangkapan layar berikut:

masukkan deskripsi gambar di sini

MsrButterfly
sumber
7
Sudahkah Anda memberi awalan nama kelas entitas dengan nama modul, seperti yang didokumentasikan dalam Mengimplementasikan Subkelas Objek Terkelola Data Inti ?
Martin R
@MartinR: Lihat pembaruan pertanyaan saya.
MsrButterfly
2
Kelas harus "YourAppName.User", lihat dokumentasi (link di komentar saya sebelumnya).
Martin R
@MartinR: Terima kasih atas bantuan Anda. Berhasil.
MsrButterfly
Hal terbaik adalah menghapus kelas-kelas itu dan membuatnya kembali. Ini berhasil untuk saya
Abhishek

Jawaban:

221

Pembaruan untuk Xcode 7 (final): Mempersiapkan nama modul ke kelas (seperti di Xcode 6 dan rilis beta awal Xcode 7) tidak lagi diperlukan. Dokumentasi Apple yang Mengimplementasikan Subkelas Objek Terkelola Data Inti telah diperbarui sebagaimana mestinya.

Pemeriksa Model Data sekarang memiliki dua kolom "Kelas" dan "Modul" untuk entitas:

masukkan deskripsi gambar di sini

Saat Anda membuat subkelas objek terkelola Swift untuk entitas tersebut, kolom "Module" disetel ke "Current Product Module", dan dengan setelan ini, pembuatan instance berfungsi baik di aplikasi utama maupun dalam pengujian unit. Subkelas objek terkelola tidak boleh ditandai dengan @objc(classname)(ini diamati di https://stackoverflow.com/a/31288029/1187415 ).

Atau, Anda dapat mengosongkan bidang "Modul" (ini akan menampilkan "Tidak Ada") dan menandai subkelas objek terkelola dengan @objc(classname)(ini diamati di https://stackoverflow.com/a/31287260/1187415 ).


Catatan: Jawaban ini awalnya ditulis untuk Xcode 6. Ada beberapa perubahan dalam berbagai rilis Xcode 7 beta sehubungan dengan masalah ini. Karena ini adalah jawaban yang diterima dengan banyak suara positif dan tautan ke sana, saya telah mencoba meringkas situasi untuk versi final Xcode 7 saat ini.

Saya melakukan "penelitian" saya sendiri dan membaca semua jawaban untuk pertanyaan ini dan pertanyaan serupa CoreData: peringatan: Tidak dapat memuat nama kelas . Jadi atribusi berlaku untuk semuanya, meskipun saya tidak mencantumkannya secara spesifik!


Jawaban sebelumnya untuk Xcode 6 :

Seperti yang didokumentasikan dalam Menerapkan Subkelas Objek Terkelola Data Inti , Anda harus mengawali nama kelas entitas di bidang Kelas di inspektur entitas model dengan nama modul Anda, misalnya "MyFirstSwiftApp.User".

Martin R
sumber
2
Yang ini berhasil untuk saya. Pertanyaan: Bagaimana jika data inti disertakan dalam kerangka kerja, bagaimana cara memberi awalan nama subkelas ManagedObject karena belum ada aplikasi yang sebenarnya?
Allan Macatingrao
9
@ Allan: Anda dapat mencoba @objc(ClassName)metode yang disarankan dalam jawaban Christer.
Martin R
8
Ini berfungsi, tetapi setelah saya menetapkan nama kelas ke "APPNAME.User" di inspektur entitas, saya tidak dapat membuat ulang kelas model: Xcode tampaknya bingung dengan awalan, dan menghasilkan file / kelas dengan nama NAMA APLIKASI. Apakah saya melewatkan sesuatu?
Pascal Bourque
1
Bagaimana jika Anda mendapatkan kesalahan ini di Objective-C saat menggunakan data inti di pustaka statis?
George Taskos
1
@Suragch: Saya sekarang akhirnya memperbarui jawabannya, saya berharap semuanya sudah benar sekarang.
Martin R
62

Hanya sebagai catatan samping. saya memiliki masalah yang sama. Dan yang harus saya lakukan hanyalah menambahkan @objc(ClassName)file kelas saya.

Contoh:

@objc(Person)
class Person { }

Dan itu memecahkan masalah saya.

Christer
sumber
1
Anda mendefinisikan typealias (<% ProjectName%>. Person -> Person) di Objective-C dengan cara itu, sehingga berfungsi.
MsrButterfly
Sepertinya Apple lupa untuk sepenuhnya mengubahnya menjadi swift .. tidak tahu mengapa tapi ini memperbaikinya untuk saya dengan cukup lembut
Jiří Zahálka
7
Ini sangat berguna jika Anda memiliki proyek dengan beberapa target, di mana setiap target memiliki model CoreData yang sama. Dalam kasus ini, tidak mungkin untuk memberi awalan nama kelas dengan yang dari pengidentifikasi target karena membuat model CD berguna hanya untuk salah satu target.
djbp
@djbp Dan "kenapa tidak?" Saya ingin tahu Saya suka konsep namespacing, tetapi ini membuat saya ingin membuang MacBook saya ke luar jendela (saya memiliki aplikasi dengan ekstensi, dan mengalami masalah ini saat menjalankan ekstensi). Harus ada cara yang "benar" untuk melakukan ini dengan namespace, saya tidak bisa memahaminya.
S'pht'Kr
Yup ini berhasil untuk saya saat bekerja dengan model data bersama di ruang kerja
naz
31

Jawaban yang diterima untuk pertanyaan ini membantu saya menyelesaikan masalah yang sama tetapi saya memiliki peringatan yang menurut saya akan membantu orang lain. Jika nama proyek (modul) Anda memiliki spasi di dalamnya, Anda harus mengganti spasi dengan garis bawah. Sebagai contoh:

Entitas: Kelas MyEntity: My_App_Name.MyClass

Mannix
sumber
Persis yang saya cari! Bersulang!
manosim
Ketika kita menetapkan nama kelas dengan AppName.ClassName, Xcode 9 menghapus titik dan membuat kelas tanpa titik. Jadi ini tidak lagi di Xcode 9. *.
yo2bh
17

Ingatlah untuk menghapus modul Anda :

masukkan deskripsi gambar di sini

Bartłomiej Semańczyk
sumber
1
Ini memperbaiki masalah saya!
simme
2
Ini memperbaiki masalah saya.
Jason Huh
9

Bergantung pada apakah Anda menjalankan App vs Test, masalahnya mungkin adalah aplikasi yang dicari <appName>.<entityName>dan saat dijalankan sebagai pengujian, tampilannya akan seperti itu <appName>Tests.<entityName>. Solusi yang saya gunakan saat ini (Xcode 6.1) adalah TIDAK mengisi Classbidang di UI CoreData, dan melakukannya dalam kode.

Kode ini akan mendeteksi jika Anda menjalankan App vs Tests dan menggunakan nama modul yang benar dan memperbarui managedObjectClassName.

lazy var managedObjectModel: NSManagedObjectModel = {
    // The managed object model for the application. This property is not optional...
    let modelURL = NSBundle.mainBundle().URLForResource("Streak", withExtension: "momd")!
    let managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL)!

    // Check if we are running as test or not
    let environment = NSProcessInfo.processInfo().environment as [String : AnyObject]
    let isTest = (environment["XCInjectBundle"] as? String)?.pathExtension == "xctest"

    // Create the module name
    let moduleName = (isTest) ? "StreakTests" : "Streak"

    // Create a new managed object model with updated entity class names
    var newEntities = [] as [NSEntityDescription]
    for (_, entity) in enumerate(managedObjectModel.entities) {
        let newEntity = entity.copy() as NSEntityDescription
        newEntity.managedObjectClassName = "\(moduleName).\(entity.name)"
        newEntities.append(newEntity)
    }
    let newManagedObjectModel = NSManagedObjectModel()
    newManagedObjectModel.entities = newEntities

    return newManagedObjectModel
}()
Ludovic Landry
sumber
1
Saya mencoba solusi Anda, tetapi saya mendapatkan "kesalahan fatal: elemen NSArray gagal cocok dengan jenis Elemen Array Swift" saat mentransmisikan NSManagedObject ke kelas sebenarnya. Sebenarnya bukan saat mentransmisikan dirinya sendiri, tetapi saat mencoba masuk ke loop for.
Rodrigo Ruiz
1
Contoh itu tidak berfungsi jika Anda memiliki jenis warisan apa pun dalam model Anda. Untuk setiap entitas baru, Anda juga perlu mengulangi subentit dan memperbaruinya dengan entitas baru yang Anda buat.
Anton
8

Jika Anda menggunakan tanda hubung dalam nama proyek Anda seperti "Aplikasi-Saya", gunakan garis bawah dan bukan tanda hubung seperti "My_App.MyManagedObject". Secara umum, lihat nama file xcdatamodeld dan gunakan awalan yang sama seperti pada nama itu. Yaitu "My_App_1.xcdatamodeld" membutuhkan awalan "My_App_1"

Rien
sumber
1
Wow. Terima kasih terima kasih terima kasih. Saya tertarik untuk mengetahui di mana di dokumen Apple bahwa nugget kecil itu :)
nh32rg
5

Ini dapat membantu mereka yang mengalami masalah yang sama. Saya dulu, dengan Swift 2 dan Xcode 7 beta 2.

Solusi dalam kasus saya adalah untuk komentar @objc(EntityName)di EntityName.swift.

enreas
sumber
3

Saya mendapat peringatan yang sama, meskipun aplikasi saya tampak berjalan dengan baik. Masalahnya adalah saat menjalankan Editor> Buat Subkelas NSManagedObject di layar terakhir saya menggunakan lokasi Grup default, tanpa Target yang ditampilkan atau dicentang, yang menyimpan subkelas di direktori MyApp atas tempat MyApp.xcodeproj berada.
Peringatan itu hilang ketika saya malah mengubah Grup menjadi di subfolder MyApp dan memeriksa target MyApp.

Daniel Ford
sumber
2

Jawaban di atas sangat membantu. Pemeriksaan kewarasan cepat ini dapat menghemat waktu Anda. Masuk ke Project> Build Phases> Compile Sources dan hapus xcdatamodeld dan file model Anda dengan tombol "-", lalu tambahkan kembali dengan tombol "+". Bangun kembali - itu mungkin bisa menangani itu.

trevorgrayson
sumber
2

Omong-omong, berhati-hatilah dengan apa yang Anda tambahkan sebagai awalan: Aplikasi Saya disebut "ABC-def" dan Xcode telah mengubah "-" menjadi "_".

Untuk amannya, lihat finder, temukan file proyek Anda dan lihat apa yang tertulis untuk model data Anda (misalnya "ABC_def.xcdatamodeld") dan gunakan apa yang tertulis di sana PERSIS !!!

Mike
sumber
1

Jawaban di atas membantu saya menyelesaikan berbagai masalah yang terkait dengan Objective-C (mungkin itu akan membantu seseorang):

Jika Anda memfaktorkan ulang nama entitas, jangan lupa untuk mengubah "Kelas" di "Panel Utilitas" juga.

Vive
sumber
0

Jawaban di atas membantu saya tetapi ini dapat membantu seseorang. Jika seperti saya, Anda melakukannya dan masih mengalami masalah, ingatlah untuk 'membersihkan proyek Anda'. Untuk XCode8, Produk> Bersihkan. Lalu lari lagi.

Olaolu Akinsete
sumber
0

Di Xcode 7 Entitas dan nama Kelas bisa sama tetapi Codegen harus Definisi Kelas. Dalam hal ini tidak akan ada peringatan dll.

masukkan deskripsi gambar di sini

dcaric.dll
sumber