在Xcode 6b3上使用Swift时,我很难简单地插入一个具有一对一关系的NSManagedObject。
我把我的代表GitHub,但失败的代码(在SwiftCoreDataRelationshipReproTests.swift
的testSwiftToOne
单元测试方法)归结为:
let momURL : NSURL = NSBundle.mainBundle().URLForResource("SwiftCoreDataRelationshipRepro",
withExtension: "momd")
let mom : NSManagedObjectModel = NSManagedObjectModel(contentsOfURL: momURL)
let psc : NSPersistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: mom);
let ps : NSPersistentStore = psc.addPersistentStoreWithType(
NSInMemoryStoreType,
configuration: nil,
URL: nil,
options: nil,
error: nil)
let moc : NSManagedObjectContext = NSManagedObjectContext()
moc.persistentStoreCoordinator = psc
// This throws an NSInvalidArgumentException: "An NSManagedObject of class 'NSManagedObject' must have a valid NSEntityDescription."
NSManagedObject(
entity: NSEntityDescription.entityForName("Pet", inManagedObjectContext: moc),
insertIntoManagedObjectContext: moc)
看起来应该行得通。没有什么棘手。
我非常相似的具有多对多关系的Person
实体可以用Swift正确插入(并保存)(通过testSwiftToMany
测试证明)。更复杂的Objective-C版本也成功使用相同的数据模型(通过testObjcToOneAndToMany
测试)。
下面是整个例外:
file:///%3Cunknown%3E: test failure: -[SwiftCoreDataRelationshipReproTests testSwiftToOne()] failed: failed: caught "NSInvalidArgumentException", "An NSManagedObject of class 'NSManagedObject' must have a valid NSEntityDescription."
(
0 CoreFoundation 0x00007fff8dd6525c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff84ce5e75 objc_exception_throw + 43
2 CoreData 0x00007fff8765dd16 -[NSManagedObject initWithEntity:insertIntoManagedObjectContext:] + 550
3 SwiftCoreDataRelationshipReproTests 0x0000000100394d4a _TTOFCSo15NSManagedObjectcfMS_FT6entityGSQCSo19NSEntityDescription_30insertIntoManagedObjectContextGSQCSo22NSManagedObjectContext__S_ + 42
4 SwiftCoreDataRelationshipReproTests 0x00000001003946bd _TFCSo15NSManagedObjectCfMS_FT6entityGSQCSo19NSEntityDescription_30insertIntoManagedObjectContextGSQCSo22NSManagedObjectContext__S_ + 93
5 SwiftCoreDataRelationshipReproTests 0x0000000100393450 _TFC35SwiftCoreDataRelationshipReproTests35SwiftCoreDataRelationshipReproTests14testSwiftToOnefS0_FT_T_ + 816
6 SwiftCoreDataRelationshipReproTests 0x00000001003934c2 _TToFC35SwiftCoreDataRelationshipReproTests35SwiftCoreDataRelationshipReproTests14testSwiftToOnefS0_FT_T_ + 34
7 CoreFoundation 0x00007fff8dc50a5c __invoking___ + 140
8 CoreFoundation 0x00007fff8dc508c4 -[NSInvocation invoke] + 308
9 XCTest 0x00000001003b023a -[XCTestCase invokeTest] + 253
10 XCTest 0x00000001003b03ac -[XCTestCase performTest:] + 142
11 XCTest 0x00000001003b8ad0 -[XCTest run] + 257
12 XCTest 0x00000001003af68b -[XCTestSuite performTest:] + 379
13 XCTest 0x00000001003b8ad0 -[XCTest run] + 257
14 XCTest 0x00000001003af68b -[XCTestSuite performTest:] + 379
15 XCTest 0x00000001003b8ad0 -[XCTest run] + 257
16 XCTest 0x00000001003af68b -[XCTestSuite performTest:] + 379
17 XCTest 0x00000001003b8ad0 -[XCTest run] + 257
18 XCTest 0x00000001003acc8f __25-[XCTestDriver _runSuite]_block_invoke + 56
19 XCTest 0x00000001003b773d -[XCTestObservationCenter _observeTestExecutionForBlock:] + 162
20 XCTest 0x00000001003acbc8 -[XCTestDriver _runSuite] + 269
21 XCTest 0x00000001003ad34a -[XCTestDriver _checkForTestManager] + 551
22 XCTest 0x00000001003bb879 +[XCTestProbe runTests:] + 175
23 Foundation 0x00007fff8e0aacb7 __NSFireDelayedPerform + 333
24 CoreFoundation 0x00007fff8dccc494 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
25 CoreFoundation 0x00007fff8dccbfcf __CFRunLoopDoTimer + 1151
26 CoreFoundation 0x00007fff8dd3d5aa __CFRunLoopDoTimers + 298
27 CoreFoundation 0x00007fff8dc87755 __CFRunLoopRun + 1525
28 CoreFoundation 0x00007fff8dc86f25 CFRunLoopRunSpecific + 309
29 HIToolbox 0x00007fff8e566a0d RunCurrentEventLoopInMode + 226
30 HIToolbox 0x00007fff8e566685 ReceiveNextEventCommon + 173
31 HIToolbox 0x00007fff8e5665bc _BlockUntilNextEventMatchingListInModeWithFilter + 65
32 AppKit 0x00007fff8538e26e _DPSNextEvent + 1434
33 AppKit 0x00007fff8538d8bb -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122
34 AppKit 0x00007fff853819bc -[NSApplication run] + 553
35 AppKit 0x00007fff8536c7a3 NSApplicationMain + 940
36 SwiftCoreDataRelationshipRepro 0x000000010000ad55 top_level_code + 37
37 SwiftCoreDataRelationshipRepro 0x000000010000ad8a main + 42
38 libdyld.dylib 0x00007fff861115fd start + 1
)
所以我无法解决这个问题,但我认为我把它缩小到框架或Swift的错误。使用entityForName
相当于直接从managedObjectModel中获取实体,所以我试图这样做:
let entities = moc.persistentStoreCoordinator.managedObjectModel.entitiesByName;
let keys = Array(entities.keys)
let petVar : String = keys[1] as String
let isEqual1 = (petVar == "Pet") // true
let isEqual2 = (petVar.hashValue == "Pet".hashValue) // true
let result1 = entities["Pet"] // nil
let result2 = entities[petVar] // non-nil
let result3 = entities.bridgeToObjectiveC().objectForKey("Pet".bridgeToObjectiveC()) // nil
let result4 = entities.bridgeToObjectiveC().objectForKey(petVar.bridgeToObjectiveC()) // non-nil
// Doesn't Pass
XCTAssertNotNil(NSEntityDescription.entityForName("Pet", inManagedObjectContext: moc));
// Passes
XCTAssertNotNil(NSEntityDescription.entityForName(petVar, inManagedObjectContext: moc));
它适用于从字典中取出的键,但不适用于与键等效的字符串(即使哈希值相同)。
我认为这非常明确地表明,要么在框架中,要么在Swift本身存在bug。我正在运行Xcode (6b3)和10.9.4