我遇到核心数据的有线问题。使用iOS 10中的Swift3,每次使用
获取或存储数据时,都会获得托管对象上下文 func getContext () -> NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
在我的应用中,我有两个实体'用户'和' Ledger'。我想为用户分配分类帐,但用户可以有多个分类帐。因此,我有一个UserTableView,我可以在其中显示用户和UserViewController类,我在其中创建一个用户。我对分类账也一样。在创建分类帐时,我还会得到一个所有用户的列表,我从中选择一个用户,哪个用户应该分配到分类帐,反之亦然。
如上所述保存时,我收到错误
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for to-one relationship: property = "user"; desired type = User; given type = User;
我的数据模型如下: Data Model
非常感谢任何帮助:)
答案 0 :(得分:6)
我有同样的问题。在我的情况下,当我运行单元测试时发生了这种情况。在这种情况下,内存中同时存在两个核心数据堆栈,一个用于应用程序工具,另一个用于运行单元测试。
解决这个问题的第一个线索是在设置关系属性之前放置一个断言,以确保我设置的对象的实体类型与关系的预期实体类型相同。它们应该是相同的,在我的情况下它们不是。
在我的情况下,我有MatchRequest
与Player
有一对一的关系,称为"发起人"。所以我的断言如下:
let player = try Player.findLocal(for: matchRequest.initiator, in: moc, createIfMissing: true)
let expectedEntity = self.entity.relationshipsByName["initiator"]!.destinationEntity!
assert(player!.entity === expectedEntity, "Player returned doesn't have the same entity type")
self.initiator = player
上述断言失败,我怀疑它类似于Core Data使用的导致参数异常的断言。
检查Player.entity()时,它将返回导致失败的同一实体实例。
我认为问题的根源在于Core Data正在为核心数据堆栈中错误共享的实体设置一些静态属性。当从一个堆栈调用而不调用另一个堆栈时,调用MyManagedObject.entity()将正常工作。
因此,要解决这个问题,当我创建我的Player对象以进入关系时,我会使用较旧的NSEntityDescription.insertNewObject(...)
API而不是较新的MyManagedObject(context:)
构造函数来获取实体。这可确保将正确的实体用于给定的托管对象上下文。
所以,回顾一下:
// SOMETIMES FAILS if you have more than one core data stack:
result = Player(context: managedObjectContext)
// ALWAYS WORKS:
result = NSEntityDescription.insertNewObject(forEntityName: "Player", into: managedObjectContext) as? Player
答案 1 :(得分:0)
我遇到了同样的问题,但是我非常确定自己没有像以前的回答那样有2个核心数据栈。
最后,我意识到我已经使用if ( args.Button == 2) // right button clicked
{
// Code to display your dialogbox
}
关键字初始化了对$headers ='From: "intranet "<administratif@groupname.com>'."\n";
$headers .='Reply-To: administratif@groupname.com'."\n";
$headers .='Content-Type: text/plain; charset=utf-8 '."\n";
$headers .='Content-Transfer-Encoding: 8bit';
mail($to, $subject, $message, $headers);
的引用以及视图上下文和背景上下文。我还有一堆代码在后台线程中进行了一些繁重的工作,并使用上述堆栈进行保存。
Apple的文档说:“如果标有lazy修饰符的属性是 同时被多个线程访问,并且该属性没有 尚未初始化,无法保证该属性将被 仅初始化一次。”
因此,这种不幸的情况是解决此错误的另一种方法。解决方案:在执行大量后台/前台线程工作时,请确保不要NSStoreCoordinator
专门在您的Core Data Stack中进行任何操作。
我希望它将来对某人有帮助。对于未来的开发人员,如果您在这里:祝你好运。
答案 2 :(得分:0)
我遇到了同样的问题。我认为@Chris已明确给出了原因。执行测试时,内存中有多个实例。
解决方案是将NSPersistentContainer
的初始部分移到setUpWithError
和tearDownWithError
中。
在下面的示例中,CoreDataManager
处理init
中的NSPersistentContainer
。
代码如下:
之前
class FooTests: XCTestCase {
var manager: CoreDataManager = CoreDataManager()
}
之后
class FooTests: XCTestCase {
var manager: CoreDataManager?
override func setUpWithError() throws {
manager = CoreDataManager(inMemory: true)
}
override func tearDownWithError() throws {
manager = nil
}
}