CoreData: คำเตือน: ไม่สามารถโหลดคลาสที่ชื่อ


95

ฉันกำลังทำซ้ำแอพ Objective-C TV Show ที่มีอยู่กับ Swift เวอร์ชันใหม่โดยใช้ Xcode 6.1 และกำลังมีปัญหากับ CoreData

ฉันได้สร้างแบบจำลองของ 4 เอนทิตีสร้างคลาสย่อย NSManagedObject (ใน Swift) และไฟล์ทั้งหมดมีการกำหนดเป้าหมายแอปที่เหมาะสม (สำหรับ 'Compile Sources')

ฉันยังคงได้รับข้อผิดพลาดนี้ทุกครั้งที่พยายามแทรกเอนทิตีใหม่:

CoreData: คำเตือน: ไม่สามารถโหลดคลาสที่ชื่อ 'Shows' สำหรับเอนทิตี 'Shows' ไม่พบคลาสโดยใช้ 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 ขึ้นไป)

คุณต้องลบข้อความ "Current Product Module" ในโมดูล!

จาก Xcode7 beta 3

2.
คุณควรปฏิบัติตามคำแนะนำที่ใช้บ่อยเพื่อรวมไว้ด้วย

@objc(Show)

เหนือชั้นเรียนของคุณ

หมายเหตุ : หากคุณใช้ Xcode 7 beta 4 หรือใหม่กว่าขั้นตอนนี้เป็นทางเลือก

3.
นอกจากนี้ยังให้แน่ใจว่าจะโยนNSManagedObjectวัตถุที่มีการจัดการที่สร้างขึ้นไปที่ระดับที่เหมาะสมเป็นค่าเริ่มต้นจะเป็นเพียง

var newShow = NSEntityDescription.insertNewObjectForEntityForName("Show", 
                 inManagedObjectContext: context) as Show

3
ขอบคุณ! ฉันได้ทำการอัปเดตหลักการตั้งชื่อที่แนะนำแล้วและเป็น "@objc (Show)" ที่ดูเหมือนจะทำเคล็ดลับในการแก้ไขข้อผิดพลาด 'ไม่สามารถโหลดคลาส ... ' ชื่นชมมาก!
JimmyJammed

สวัสดี @Mundi ขอบคุณมาก! ยังจำแหล่งที่มาได้ไหม
iamdavidlam

1
ดูเช่นคำถามนี้ มีข้อมูลเพียงพอที่จะทำความเข้าใจว่าเกิดอะไรขึ้น
Mundi

4
ที่น่าสนใจพอฉันต้องลบ @objc(MyClass)
ซานตาคลอส

1
@ มุนดิคุณอาจต้องการอัปเดตคำตอบของคุณอีกครั้ง ดูอัปเดตคำตอบของ khunshan
Suragch

76

อัปเดต SWIFT 2 / XCODE 7:

ปัญหานี้ (ดูความคิดเห็น 3 เมษายนของฉันเกี่ยวกับคำตอบนี้ด้วย) ได้รับการแก้ไขแล้วในSwift 2และXCode 7รุ่นเบต้าโดย Apple ดังนั้นตอนนี้คุณไม่จำเป็นต้องใช้@objc(myEntity)Swift ตามที่ Mundi ตอบหรือใช้ " MyAppName." นำหน้าชื่อชั้นเรียนของคุณ มันจะหยุดทำงาน ดังนั้นลบสิ่งเหล่านี้ออกเพียงแค่ใส่Classชื่อในไฟล์แล้วเลือกCurrent Working Moduleเป็นโมดูล และไชโย!

การเลือกโมดูลการทำงานปัจจุบัน

แต่สำหรับผู้ที่ใช้@objc(myEntity)ใน Swift (เช่นฉัน) คุณสามารถใช้โซลูชันอื่นแทนซึ่งทำงานได้อย่างราบรื่น

ในคลาสที่ถูกต้อง xcdatamodel ควรมีลักษณะดังนี้:

การตั้งค่าคลาส

จัดให้เลย Module.Classเป็นรูปแบบสำหรับ CoreData ใน Swift และ XCode 6 คุณจะต้องมีขั้นตอนเดียวกันนี้เมื่อใช้คลาสCustom Policyใน Model Policy หรือ CoreData อื่น ๆ หมายเหตุ: ในรูปภาพชื่อและคลาสควรเป็นรถยนต์และ MyAppName.Car (หรือชื่อนิติบุคคลของคุณ) นี่Userคือการพิมพ์ผิด


ปัญหาในการแก้ปัญหานี้คือคลาสเอนทิตีที่สร้างโดยอัตโนมัติจะทำงานไม่ถูกต้องอีกต่อไป (จะสร้างคลาสเดียวที่มีชื่อโมดูล) ดู: สร้าง NSManagedObject subclass ไม่ได้สร้างอย่างถูกต้อง
milos

คุณต้องใช้โซลูชันหลังจากสร้างคลาสเอนทิตี NSManagedObject อาจเป็นข้อผิดพลาด xcode 6.xx ที่จะถูกลบออก
khunshan

2
ใช่สิ่งนี้จะได้รับการแก้ไขอย่างไม่ต้องสงสัย คลาสที่สร้างขึ้นโดยอัตโนมัติควรประดับด้วย @objc อยู่แล้ว (<ชื่อคลาสที่ป้อนในตัวตรวจสอบเอนทิตี>) มิฉะนั้น Apple จะทำให้สิ่งนี้ไม่จำเป็นสำหรับการเริ่มต้น
milos

2
สำหรับคนที่ยังอ่านข้อความนี้ การใช้ ' MyAppName.Car ' ไม่ได้ผลสำหรับฉันมันใช้งานได้เมื่อฉันลบ ' MyAppName. 'ส่วน. ดังนั้นCarสำหรับทั้งสองช่องก็เป็นเคล็ดลับ
Gideon

1
คุณแชมป์ !!!! ให้ person = NSEntityDescription.insertNewObject (forEntityName: "Person" เข้าสู่: บริบท) เป็น! บุคคล
Abhimanyu Rathore

36

เมื่อใช้ Xcode 7 และ Swift ล้วนๆจริงๆแล้วฉันต้องลบออก @objc(MyClass)จากNSManagedObjectคลาสย่อยที่สร้างขึ้นโดยอัตโนมัติ(สร้างจากEditor> Create NSManagedObject Subclass...)


4
ว้าวขอบคุณสำหรับการโพสต์คำตอบนี้ ฉันกำลังจะเริ่มเอาหัวโขกกับกำแพง
Zia

ปัญหาเดียวกันที่นี่ - ส่งข้อบกพร่องแล้ว
MirekE

ทำงานให้ฉันด้วย ต้องลบออก แปลกประหลาด.
Kent

จากการทดลองของฉันดูเหมือนเป็นผลบวกลวง
Mundi

ฉันต้องลบออกและตั้งค่าโมดูลผลิตภัณฑ์ปัจจุบันเท่านั้นจึงใช้งานได้
Oleg Sherman

13

ใน Xcode 7 เบต้า 2 (และผมเชื่อว่า 1) ในการกำหนดค่ารูปแบบวัตถุที่จัดการใหม่ชนิดFileถูกตั้งค่าเป็นโมดูลและชั้นของวัตถุที่แสดงให้เห็นในการกำหนดค่าเป็นCurrent Product Module.File

โมดูลประเภทอ็อบเจ็กต์ที่มีการจัดการตั้งค่าเป็น "โมดูลผลิตภัณฑ์ปัจจุบัน" ใน Xcode 7

การลบการตั้งค่าโมดูลให้ว่างเปล่าหรือลบการหยุดแบบเต็มดังนั้นชื่อคลาสในคอนฟิกูเรชันจึงFileเป็นการกระทำที่เทียบเท่ากันเนื่องจากแต่ละตัวทำให้เกิดการเปลี่ยนแปลงอื่น ๆ การบันทึกการกำหนดค่านี้จะลบข้อผิดพลาดที่อธิบายไว้

โมดูลของอ็อบเจ็กต์ที่มีการจัดการตั้งค่าเป็นว่างใน Xcode 7


9

ใน Xcode 6.1.1 คุณไม่จำเป็นต้องเพิ่มแอตทริบิวต์ @objc เนื่องจากเอนทิตีฐานเป็นชุดย่อยของคลาส objc (NSManagedObject) (ดูที่ความเข้ากันได้ของ Swift Typeใน CoreData จำเป็นต้องมีชื่อ Module.Class แบบเต็มโปรดทราบว่าโมดูล . ชื่อคือสิ่งที่มีการตั้งค่าในการตั้งค่ารูปร่าง -> บรรจุภัณฑ์ -> สินค้าชื่อโมดูลโดยค่าเริ่มต้นนี้ถูกตั้งค่า $ (PRODUCT_NAME: c99extidentifier) ซึ่งจะเป็นชื่อของเป้าหมาย


ใช่ นี่คือคำตอบสมัยใหม่ (xcode 6.3.2) การใช้ชื่อบันเดิลที่ถูกต้องเป็นกุญแจสำคัญ ในกรณีของฉันมันเปลี่ยนmy-productเป็นmy_productและสิ่งนี้สร้างความแตกต่างทั้งหมดให้กับ Core Data
SimplGy

5

ด้วย xCode 7 และ Swift 2.0 เวอร์ชันคุณไม่จำเป็นต้องเพิ่ม @objc (NameOfClass) เพียงแค่เปลี่ยนการตั้งค่าเอนทิตีในแท็บ "แสดงตัวตรวจสอบโมเดลข้อมูล" ดังต่อไปนี้ -

ชื่อ - "ชื่อเอนทิตีของคุณ"

คลาส - "ชื่อเอนทิตีของคุณ"

โมดูล - "โมดูลผลิตภัณฑ์ปัจจุบัน"

ป้อนคำอธิบายภาพที่นี่

รหัสสำหรับไฟล์คลาสเอนทิตีจะเป็นอย่างไร (ในรหัสของฉันเอนทิตีคือครอบครัว) -

import UIKit
import CoreData

class Family: NSManagedObject {

   @NSManaged var member : AnyObject
}

ตัวอย่างนี้ใช้งานได้ดีในแอปของฉันด้วย xCode 7.0 + swift 2.0


3

อย่าลืมแทนที่PRODUCT_MODULE_NAMEด้วยชื่อโมดูลผลิตภัณฑ์ของคุณ

เมื่อสร้างเอนทิตีใหม่คุณต้องไปที่ Data Model Inspector (แท็บสุดท้าย) และแทนที่PRODUCT_MODULE_NAMEด้วยชื่อโมดูลของคุณมิฉะนั้นจะทำให้เกิดclass not foundข้อผิดพลาดเมื่อสร้างผู้ประสานงานร้านค้าถาวร


2

คุณต้องใช้ (อย่างน้อยกับ Xcode 6.3.2) Module.Class เมื่อทำการแคสต์ของคุณเช่นสมมติว่าโมดูลของคุณ (เช่นชื่อผลิตภัณฑ์) คืออาหารและคลาสของคุณคือผลไม้

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

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

สรุป:

  • รวมชื่อโมดูลเมื่อกำหนดเอนทิตีใน Data Model Editor (ชื่อ: Fruit, Class: Food.Fruit)
  • เมื่อเข้าถึงเอนทิตีในโค้ด (ieSWIFT) ให้แคสต์ด้วย Module.class (เช่น Food.Fruit)

ขอบคุณจุดที่สองสำคัญมาก ฉันต้องใช้ "Module.Class" ในการแคสต์
Zoyt


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 และเปิดโครงการของคุณใหม่อีกครั้ง มันใช้ได้กับฉัน คำตอบนี้จะเกิดขึ้นก็ต่อเมื่อคุณไม่ได้รับคำแนะนำ แต่หากไฟล์ของคุณไม่ได้รับการสร้างขึ้นให้ลองใช้คำตอบข้างต้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.