Không thể tìm thấy lớp con cụ thể của NSManagedObject


136

Tôi đang làm việc để phát triển một ứng dụng với Core Data. Khi tôi tạo một cá thể bằng cách sử dụng:

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

Tôi đã nhận được một cảnh báo trong nhật ký:

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

Làm thế nào tôi có thể sửa chữa nó?

Và một câu hỏi khác, làm thế nào tôi có thể định nghĩa một phương thức cá thể trong lớp con NSManagedObject?

Biên tập:

Tôi đã chỉ định lớp của thực thể như trong ảnh chụp màn hình sau:

nhập mô tả hình ảnh ở đây


7
Bạn đã đặt tiền tố tên lớp thực thể với tên mô-đun, như được ghi lại trong Thực hiện các lớp con đối tượng được quản lý dữ liệu lõi ?
Martin R

@MartinR: Xem cập nhật câu hỏi của tôi.
MsrButoston

2
Lớp nên là "YourAppName.User", xem tài liệu (liên kết trong bình luận trước của tôi).
Martin R

@MartinR: Cảm ơn sự giúp đỡ của bạn. Nó hoạt động.
MsrButoston

Điều tốt nhất là xóa các lớp đó và tạo lại nó. Điều này làm việc cho tôi
Abhishek

Câu trả lời:


220

Cập nhật cho Xcode 7 (cuối cùng): Việc chuẩn bị tên mô-đun cho lớp (như trong Xcode 6 và các bản phát hành beta đầu tiên của Xcode 7) không còn cần thiết nữa. Tài liệu Apple Thực hiện các lớp con đối tượng được quản lý dữ liệu lõi đã được cập nhật tương ứng.

Trình kiểm tra Mô hình Dữ liệu hiện có hai trường "Lớp" và "Mô-đun" cho một thực thể:

nhập mô tả hình ảnh ở đây

Khi bạn tạo một lớp con đối tượng được quản lý Swift cho thực thể, trường "Mô-đun" được đặt thành "Mô-đun sản phẩm hiện tại" và với cài đặt này, các phiên bản tạo hoạt động cả trong ứng dụng chính và trong các thử nghiệm đơn vị. Lớp con đối tượng được quản lý không được đánh dấu @objc(classname)(điều này được quan sát thấy trong https://stackoverflow.com/a/31288029/1187415 ).

Ngoài ra, bạn có thể làm trống trường "Mô-đun" (nó sẽ hiển thị "Không") và đánh dấu các lớp con đối tượng được quản lý bằng @objc(classname)(điều này đã được quan sát trong https://stackoverflow.com/a/31287260/1187415 ).


Lưu ý: Câu trả lời này ban đầu được viết cho Xcode 6. Có một số thay đổi trong các bản phát hành Xcode 7 beta khác nhau liên quan đến vấn đề này. Vì nó là một câu trả lời được chấp nhận với nhiều upvote và liên kết đến nó, tôi đã cố gắng tóm tắt tình huống cho phiên bản Xcode 7 hiện tại.

Tôi đã thực hiện cả "nghiên cứu" của riêng mình và đọc tất cả các câu trả lời cho cả câu hỏi này và câu hỏi tương tự CoreData: cảnh báo: Không thể tải lớp có tên . Vì vậy, sự ghi nhận thuộc về tất cả chúng, ngay cả khi tôi không liệt kê chúng một cách cụ thể!


Câu trả lời trước cho Xcode 6 :

Như được ghi lại trong việc triển khai các lớp con đối tượng được quản lý dữ liệu lõi , bạn phải đặt tiền tố tên lớp thực thể trong trường Lớp trong trình kiểm tra thực thể mô hình với tên mô-đun của bạn, ví dụ "MyFirstSwiftApp.User".


2
Đây là một trong những làm việc cho tôi. Câu hỏi: Điều gì xảy ra nếu dữ liệu cốt lõi được bao gồm trong một khung, làm thế nào để thêm tiền tố vào tên lớp con ManagedObject vì chưa có ứng dụng thực tế?
Allan Macatingrao

9
@ ALLan: Bạn có thể thử @objc(ClassName)phương pháp được đề xuất trong câu trả lời của Christer.
Martin R

8
Nó hoạt động, nhưng một khi tôi đã đặt tên lớp thành "APPNAME.User" trong trình kiểm tra thực thể, tôi không thể tạo lại các lớp mô hình: Xcode dường như bị nhầm lẫn bởi tiền tố và nó tạo ra một tệp / lớp với tên TÊN ỨNG DỤNG. Tui bỏ lỡ điều gì vậy?
Pascal Bourque

1
Điều gì xảy ra nếu bạn gặp lỗi này trong Objective-C khi sử dụng dữ liệu cốt lõi trong thư viện tĩnh?
George Taskos

1
@Suragch: Cuối cùng tôi đã cập nhật câu trả lời, tôi hy vọng rằng mọi thứ đều chính xác.
Martin R

62

Chỉ là một lưu ý phụ. Tôi gặp vấn đề tương tự. Và tất cả những gì tôi phải làm là thêm@objc(ClassName) vào tập tin lớp của tôi.

Thí dụ:

@objc(Person)
class Person { }

Và điều đó đã giải quyết vấn đề của tôi.


1
Bạn đã xác định typealias (<% ProjectName%>. Person -> Person) trong Objective-C theo cách đó, để nó hoạt động.
MsrButoston

Có vẻ như Apple đã quên chuyển đổi hoàn toàn sang swift .. không biết tại sao nhưng điều này đã khắc phục nó cho tôi khá nhẹ nhàng
Jiří Zahálka

7
Điều này đặc biệt hữu ích nếu bạn có một dự án có nhiều mục tiêu, trong đó mỗi mục tiêu chia sẻ mô hình CoreData. Trong những trường hợp này, không thể đặt tiền tố tên lớp với tên của mã định danh đích vì điều đó làm cho mô hình CD chỉ hữu ích cho một trong các mục tiêu.
djbp

@djbp Và "tại sao không?" Tôi muốn biết. Tôi thích khái niệm về không gian tên, nhưng điều này khiến tôi muốn ném MacBook ra khỏi cửa sổ (tôi có một ứng dụng có tiện ích mở rộng và gặp phải vấn đề này khi chạy tiện ích mở rộng). Phải có một cách "đúng" để làm điều này với các không gian tên, tôi chỉ không thể tìm ra nó.
S'pht'Kr

Yup này hoạt động với tôi khi làm việc với các mô hình dữ liệu được chia sẻ trong không gian làm việc
naz

31

Câu trả lời được chấp nhận cho câu hỏi này đã giúp tôi giải quyết vấn đề tương tự nhưng tôi có một lời cảnh báo mà tôi nghĩ sẽ hữu ích cho người khác. Nếu tên dự án (mô-đun) của bạn có một khoảng trắng trong đó, bạn phải thay thế khoảng trắng bằng dấu gạch dưới. Ví dụ:

Thực thể: Lớp MyEntity: My_App_Name.MyClass


Chính xác là tôi đang tìm kiếm! Chúc mừng!
manosim

Khi chúng ta đặt tên lớp bằng AppName.ClassName, Xcode 9 sẽ xóa dấu chấm và tạo một lớp không có dấu chấm. Vì vậy, điều này không còn trong Xcode 9. *.
yo2bh


9

Tùy thuộc vào việc bạn đang chạy dưới dạng Ứng dụng so với Thử nghiệm, vấn đề có thể là ứng dụng đang tìm kiếm <appName>.<entityName>và khi nào nó chạy như thử nghiệm thì nó trông như thế nào <appName>Tests.<entityName>. Giải pháp tôi sử dụng tại thời điểm này (Xcode 6.1) là KHÔNG điền vàoClass trường trong UI CoreData và thay vào đó để thực hiện bằng mã.

Mã này sẽ phát hiện nếu bạn đang chạy dưới dạng App vs Tests và sử dụng đúng tên mô-đun và cập nhật 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
}()

1
Tôi đã thử giải pháp của bạn nhưng tôi nhận được "lỗi nghiêm trọng: Phần tử NSArray không khớp với loại Phần tử mảng Swift" khi truyền NSManagedObject vào lớp thực tế của nó. Thực tế không phải khi tự đúc, mà là khi cố gắng đi vào một vòng lặp for.
Rodrigo Ruiz

1
Ví dụ đó không hoạt động nếu bạn có bất kỳ loại kế thừa nào trong mô hình của bạn. Đối với mọi thực thể mới, bạn cũng cần lặp lại trên các mục con và cập nhật chúng với các thực thể mới mà bạn đã tạo.
Anton

8

Nếu bạn đang sử dụng dấu gạch nối trong tên dự án của mình như "Ứng dụng của tôi" thì hãy sử dụng dấu gạch dưới thay vì dấu gạch nối như "My_App.MyManagedObject". Nói chung, hãy nhìn vào tên của tệp xcdatamodeld và sử dụng cùng một tiền tố như trong tên đó. Tức là "My_App_1.xcdatamodeld" yêu cầu tiền tố "My_App_1"


1
ồ Cảm ơn bạn, cảm ơn bạn, cảm ơn bạn. Tôi muốn biết vị trí của các tài liệu Apple mà nugget nhỏ đó ở đâu :)
nh32rg

5

Điều này có thể giúp những người gặp vấn đề tương tự. Tôi đã, với Swift 2 và Xcode 7 beta 2.

Giải pháp trong trường hợp của tôi là nhận xét ra @objc(EntityName)trong EntityName.swift.


3

Tôi đã có một cảnh báo tương tự, mặc dù ứng dụng của tôi có vẻ chạy tốt. Vấn đề là khi chạy Trình soạn thảo> Tạo Lớp con NSManagedObject trên màn hình cuối cùng, tôi đã sử dụng vị trí Nhóm mặc định, không có Mục tiêu nào được hiển thị hoặc kiểm tra, đã lưu lớp con trong thư mục MyApp.xcodeproj hàng đầu.
Cảnh báo biến mất khi tôi thay đổi Nhóm thành trong thư mục con MyApp và kiểm tra mục tiêu MyApp.


2

Các câu trả lời trên rất hữu ích. Kiểm tra vệ sinh nhanh chóng này có thể giúp bạn tiết kiệm thời gian. Đi vào Dự án> Xây dựng giai đoạn> Biên dịch nguồn và xóa xcdatamodeld và các tệp mô hình của bạn bằng nút "-", sau đó thêm chúng trở lại bằng nút "+". Xây dựng lại - có thể chăm sóc nó.


2

Nhân tiện, hãy cẩn thận với những gì bạn thêm làm tiền tố: Ứng dụng của tôi được gọi là "ABC-def" và Xcode đã chuyển đổi "-" thành "_".

Để an toàn nhìn vào công cụ tìm, hãy tìm các tệp dự án của bạn và xem nó nói gì cho mô hình dữ liệu của bạn (ví dụ: "ABC_def.xcdatamodeld") và sử dụng những gì được viết ở đó CHÍNH XÁC !!!


1

Các câu trả lời trên đã giúp tôi giải quyết các vấn đề khác nhau được kết nối với Objective-C (có thể nó sẽ giúp được ai đó):

Nếu bạn đã cấu trúc lại tên thực thể, đừng quên thay đổi "Lớp" trong "Bảng tiện ích".


0

Các câu trả lời trên đã giúp tôi nhưng điều này có thể giúp ai đó. Nếu như tôi, bạn đã làm chúng và vẫn đang gặp vấn đề, hãy nhớ chỉ cần 'làm sạch dự án của bạn'. Đối với XCode8, Sản phẩm> Sạch. Sau đó chạy lại.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.