当我尝试从模型中检索项目数组时,由于类的类型不匹配,我总是会遇到向下转换错误。 Swift有一个严格的命名空间,模型项与我想要的项目不同。这是我的NSManagedObject:
import Foundation
import CoreData
@objc(Boss)
class Boss: NSManagedObject {
@NSManaged var name: String
}
Testclass如下:
func testCheckIfFetchGetTheCorrectClass() {
// setup item
let entity = NSEntityDescription.entityForName("Boss", inManagedObjectContext: moc)
let boss = Boss(entity: entity!, insertIntoManagedObjectContext: moc)
boss.name = "Chef"
var bosses = [Boss]()
var request = NSFetchRequest(entityName: "Boss")
var e: NSError?
if let results = moc.executeFetchRequest(request, error: &e) {
println("results: \n\(results.description)\nCount:\(results.count)")
if let downcastedSwiftArray = results as? [Boss] {
// downcastedSwiftArray contains only UIView objects
bosses = downcastedSwiftArray
} else {
XCTAssert(false, "Down Cast Error")
}
println("Bosses : \n\(bosses.description)")
} else {
println("fetch error: \(e!.localizedDescription)")
abort();
}
// This is an example of a functional test case.
XCTAssert(true, "Pass")
}
当我运行测试时,以下类型将显示在调试器中:
bosses [NameSpaceTestTests.Boss] 0 values
results [AnyObject] 1 value
[0] Boss_Boss_ *
所以看起来result
数组包含的Boss
类项目与bosses
不匹配
阵列。
如何将获取请求的结果分配给我的数组?
您将在github上找到完整的项目。
答案 0 :(得分:4)
如果你改变了
if let downcastedSwiftArray = results as? [Boss] {
迫使向下转发
if let downcastedSwiftArray = results as! [Boss] {
由于运行时错误导致测试中止吗?
我也有向下转换到Core Data托管对象类型的问题。将NSManagedObject
sublcasses'文件添加到测试目标使得代码编译但似乎无法正常工作。 因此,不要将测试中的代码添加到测试目标本身。导入它。
@testable
在Swift引入@testable import
之前,我们被迫制作了我们想要公开测试的课程。这比我们想要的客户端暴露了更多的代码。如今,这是要走的路。
我通过制作课程public
来解决这个问题:
@objc(Boss)
public class Boss: NSManagedObject {
@NSManaged public var name: String
}
然后在测试中导入生产模块:
import MyProjectTargetName
答案 1 :(得分:3)
public
是一种解决方法,不应该用于测试依赖项。问题实际上是测试目标编译了他自己的源类版本,这不是你想要的。你最终会得到两个相同的版本。
以下步骤为我解决了这个问题:
App
和AppTests
答案 2 :(得分:0)
在Swift中,您必须指定由获取请求产生的数组的类型。 if let模式需要一个可选的强制转换。
if let result = moc.executeFetchRequest(request, error:&e) as? [Boss] {
// use result
}
答案 3 :(得分:0)
解决此问题的一种方法是使用以下内容动态更改NSManagedObject
子类的类名:
let managedObjectModel = NSManagedObjectModel.mergedModelFromBundles([NSBundle.mainBundle()])!
// Check if it is within the test environment
let environment = NSProcessInfo.processInfo().environment as! [String : AnyObject]
let isTestEnvironment = (environment["XCInjectBundle"] as? String)?.pathExtension == "xctest"
// Create the module name based on product name
let productName:String = NSBundle.mainBundle().infoDictionary?["CFBundleName"] as! String
let moduleName = (isTestEnvironment) ? productName + "Tests" : productName
let newManagedObjectModel:NSManagedObjectModel = managedObjectModel.copy() as! NSManagedObjectModel
for entity in newManagedObjectModel.entities as! [NSEntityDescription] {
entity.managedObjectClassName = "\(moduleName).\(entity.name!)"
}
这有助于解决类名不匹配的问题,因为在运行测试时,类名实际上是<Product Name>Tests.<Subclass Name>
(在您的情况下,它是NameSpaceTestTests.Boss
)