Fully qualified class names in combination with CoreData

Hi,

I have a problem with a combination of CoreData and Class naming.

I am generating the CoreData model dynamically by code. I. Have the following code fragment (highly simplified) that works:

class Test: NSManagedObject {
    @NSManaged var attribute: Date
}

class AttributeTests: XCTestCase {

  func testDefaultValueDate3() throws {
    let model = try CoreDataModel(databaseName) {
      Entity(Const.entityName, managedObjectClass: Test.self) {
        Attribute("attribute", type: Date.self)
          .defaultValue(Const.defaultDateValue3)
        }
    }
    let container = model.createInMemoryContainer()
    let testRecord(context: container.viewContext)
  }
}

The above code works as expected. Inside the model I am using String(reflecting:) to get the fully qualified name of the Test class. So far so good.

The problem arises if I move the Test class inside the test framework.

class AttributeTests: XCTestCase {


  func testDefaultValueDate3() throws {
    class Test: NSManagedObject {
        @NSManaged var attribute: Date
    }

    let model = try CoreDataModel(databaseName) {
      Entity(Const.entityName, managedObjectClass: Test.self) {
        Attribute("attribute", type: Date.self)
          .defaultValue(Const.defaultDateValue3)
        }
    }
    let container = model.createInMemoryContainer()
    let testRecord(context: container.viewContext)
  }
}

This now fails with an error message like:

An NSManagedObject of class '_TtCFC18CoreDataModelTests14AttributeTests21testDefaultValueDate3FzT_T_L_4Test' must have a valid NSEntityDescription. (NSInvalidArgumentException)

The problem is coming from the fact that I cannot figure out what the fully qualified name of the Test class is. If I check the output of the statement print(String(reflecting: Test.self)) I get the output:

CoreDataModelTests.AttributeTests.(unknown context at $1014d58f4).(unknown context at $1014d5900).Test

Does someone know how to get the fully qualified name of the Test class? Can I somehow address the "unknown context" message.

Add an @objc(Test) to the class. It doesn't matter that you are not using Objective-C. There are requirements in CoreData. Finally, it is best to keep the model in a static (especially when testing) as multiple model instances will confuse everything.

1 Like

Thank you for your reply. Just for clarity I changed it into:

class AttributeTests: XCTestCase {
  func testDefaultValueDate3() throws {
    @objc class Test: NSManagedObject {
        @NSManaged var attribute: Date
    }
    ....
}

Unfortunately this does not solve the issue. The behavior is identical.

To follow-up on myself. It turns out that you can set the class name using the following syntax:

class AttributeTests: XCTestCase {
  func testDefaultValueDate3() throws {
    @objc(Test) class Test: NSManagedObject {
        @NSManaged var attribute: Date
    }
    ....
}

I can work with this. Thanks for the support.

1 Like

Yeah, adding the class name is required to the objc declaration is required. Sorry, I should have been clearer. Good luck.