且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

NSPersistentContainer 将加载到应用程序中,不会加载到测试目标中

更新时间:2023-12-02 19:11:10

因此,简短的答案是NSPersistentContainer仅在主捆绑包中查找其模型文件,除非另行告知.尝试在不是应用程序目标(例如测试目标)的目标中使用它,并且找不到模型文件.您必须明确告诉它要使用的模型文件.因此,您必须使用Bundle来查找类型为"momd"的资源.

So the short answer is that NSPersistentContainer only looks for its model file in the main bundle unless it's told otherwise. Try to use it in a target that's not an application target (like a test target) and it won't find the model file. You have to explicitly tell it which model file to use yourself. So you have to use Bundle to find the resource, which is of type "momd".

这是我想出的:

enum LoadingError: Error {
    case doesNotExist(String)
    case corruptObjectModel(URL)
}

init?(title: String, then completion: @escaping (Error?)->()) {
    
    guard let modelURL = Bundle(for: type(of: self)).url(forResource: title, withExtension: "momd") else {
        completion(LoadingError.doesNotExist(title))
        return nil
    }

    guard let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL) else {
        completion(LoadingError.corruptObjectModel(modelURL))
        return nil
    }
    
    self.container = NSPersistentContainer(name: title, managedObjectModel: managedObjectModel)
    
    container.loadPersistentStores { description, error in
        // don't worry about retaining self, this object lives the whole life of the app
                    
        if let error = error {
            print("Error loading persistent store named \(title): \(error.localizedDescription)")
            DispatchQueue.main.async {
                completion(error)
            }
            return
        }
                               
        completion(nil)
    }
}

顺便说一句,显然您可以通过将NSPersistenContainer子类化来避免这种情况(请参阅 https://asciiwwdc.com/2018/sessions/224?q=nspersistentcontainer ).出于其他原因,这不是我的首选选项,但对其他人可能有用.

As an aside, apparently you can avoid this by subclassing NSPersistenContainer (see https://asciiwwdc.com/2018/sessions/224?q=nspersistentcontainer). This wasn't the preferred option for me for other reasons, but it may be useful for someone else.