Adr*_*ian 8 core-data ios swift
我正在尝试为我的核心数据代码添加一些单元测试.但我总是有这个问题,第一个测试总是正确运行,但第二个测试崩溃,因为实体名称为零.
我也得到这个错误:
Multiple NSEntityDescriptions claim the NSManagedObject subclass 'Gym.Exercise' so +entity is unable to disambiguate.
Failed to find a unique match for an NSEntityDescription to a managed object subclass
Run Code Online (Sandbox Code Playgroud)
所以我的猜测是我没有做正确的事情 tearDown().
override func setUp() {
super.setUp()
coreDataStack = CoreDataStack(storeType: .inMemory)
context = coreDataStack.context
}
override func tearDown() {
coreDataStack.reset()
context = nil
super.tearDown()
}
Run Code Online (Sandbox Code Playgroud)
这是我的CoreDataStack班级:
final class CoreDataStack {
var storeType: StoreType!
public init(storeType: StoreType) {
self.storeType = storeType
}
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Gym")
container.loadPersistentStores { description, error in
if let error = error {
fatalError("Unresolved error \(error), \(error.localizedDescription)")
} else {
description.type = self.storeType.type
}
}
return container
}()
public var context: NSManagedObjectContext {
return persistentContainer.viewContext
}
public func reset() {
guard let store = persistentContainer.persistentStoreCoordinator.persistentStores.first else { fatalError("No store found")}
guard let url = store.url else { fatalError("No store URL found")}
try! FileManager.default.removeItem(at: url)
NSPersistentStoreCoordinator.destroyStoreAtURL(url: url)
}
}
Run Code Online (Sandbox Code Playgroud)
并定义为destroyStoreAtURL:
extension NSPersistentStoreCoordinator {
public static func destroyStoreAtURL(url: URL) {
do {
let psc = self.init(managedObjectModel: NSManagedObjectModel())
try psc.destroyPersistentStore(at: url, ofType: NSSQLiteStoreType, options: nil)
} catch let e {
print("failed to destroy persistent store at \(url)", e)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我过去使用这段代码进行单元测试并且它有效,区别在于我NSManagedObject在编辑器中设置类时过去使用了以下配置:
Module - Global namespace
Codegen - Class Definition
Run Code Online (Sandbox Code Playgroud)
现在我使用:
Module - Current Product Module
Codegen - Manual/None
Run Code Online (Sandbox Code Playgroud)
因为我想手动添加我的类.
那么有谁知道为什么行为现在不同了?
edit - 我的NSManagedObject扩展帮助程序(在尝试检索实体名称时,错误发生在fetch()方法的第一行内):
extension Managed where Self: NSManagedObject {
public static var entityName: String {
return entity().name!
}
public static func fetch(in context: NSManagedObjectContext, configurationBlock: (NSFetchRequest<Self>) -> () = { _ in }) -> [Self] {
let request = NSFetchRequest<Self>(entityName: Self.entityName)
configurationBlock(request)
return try! context.fetch(request)
}
public static func count(in context: NSManagedObjectContext, configure: (NSFetchRequest<Self>) -> () = { _ in }) -> Int {
let request = NSFetchRequest<Self>(entityName: entityName)
configure(request)
return try! context.count(for: request)
}
public static func findOrFetch(in context: NSManagedObjectContext, matching predicate: NSPredicate) -> Self? {
guard let object = materializeObject(in: context, matching: predicate) else {
return fetch(in: context) { request in
request.predicate = predicate
request.returnsObjectsAsFaults = false
request.fetchLimit = 1
}.first
}
return object
}
public static func materializeObject(in context: NSManagedObjectContext, matching predicate: NSPredicate) -> Self? {
for object in context.registeredObjects where !object.isFault {
guard let result = object as? Self, predicate.evaluate(with: result) else {
continue
}
return result
}
return nil
}
public static func findOrCreate(in context: NSManagedObjectContext, matching predicate: NSPredicate, configure: (Self) -> ()) -> Self {
guard let object = findOrFetch(in: context, matching: predicate) else {
let newObject: Self = context.insertObject()
configure(newObject)
return newObject
}
return object
}
}
Run Code Online (Sandbox Code Playgroud)
小智 1
您应该尝试删除所有找到的 persistenceStore 实例,而不是删除第一个。
尝试用以下替换重置功能:
public func reset() {
let stores = persistentContainer.persistentStoreCoordinator.persistentStores
guard !stores.isEmpty else {
fatalError("No store found")
}
stores.forEach { store in
guard let url = store.url else { fatalError("No store URL found")}
try! FileManager.default.removeItem(at: url)
NSPersistentStoreCoordinator.destroyStoreAtURL(url: url)
}
}
Run Code Online (Sandbox Code Playgroud)
看看您是否仍然遇到问题。
| 归档时间: |
|
| 查看次数: |
365 次 |
| 最近记录: |