Swift and CoreData Casting issues in test vs non-test

后端 未结 3 845
野的像风
野的像风 2020-12-31 19:39

I\'m using Swift on Xcode 6 with CoreData.

I\'ve read the release notes and have seen this issue about making sure to mark up a core data model with a m

相关标签:
3条回答
  • 2020-12-31 19:55

    Your are totally right, the issue is the when you run the App it's looking for myAppname.myEntity and when you run as Test it's looking as myAppnameTests.myEntity. The solution I use at this time (Xcode 6.1) is to NOT fill the Class field in the CoreData UI, and to do it in code instead.

    This code will detect if you are running as App vs Tests and use the right module name and update the 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
    }()
    
    0 讨论(0)
  • 2020-12-31 19:57

    Here is an updated answer that actually worked for me. Using XCode 9.2

    Ok, I figured it out! It's not exactly intuitive though. First, I had to comment out the @objc(EntityName) line in the NSManagedObject subclasses. Then I went back to the default Module defined in the xcdatamodeld (Current Project Module). Then I had to ensure that only my test classes (and NONE of the NSManagedObject subclasses or any other source files) were compiled as part of my test project (this was critical) and @testable import AppName in my test project class files. Now it never trys to use these classes in the AppNameTests module, only AppName and the test projects can only call public or internal code...therefore all is right in the universe, yay!

    0 讨论(0)
  • 2020-12-31 20:06

    You need to add one line to you Entity.swift file to make it also an Objective-C class like this:

    @objc(YourEntity)
    class YourEntity: NSManagedObject {
        ...
    }
    

    I think this as a bug if your project does not contains any objective-c code. However, you need to add that line until this fixed.

    I learned it from here.

    Youtube video at 11:45

    0 讨论(0)
提交回复
热议问题