尝试访问托管对象属性时的 EXC_BAD_ACCESS
Posted
技术标签:
【中文标题】尝试访问托管对象属性时的 EXC_BAD_ACCESS【英文标题】:EXC_BAD_ACCESS when trying to access a managed object property 【发布时间】:2013-03-17 19:48:02 【问题描述】:我在处理核心数据+并发/嵌套 MOC 时遇到了一些问题(不确定我在使用 =P 时遇到了哪一个问题)。
我有一个方法,我传入一个托管对象 ID(我检查了它是否是永久的),并且该方法有一个子托管对象上下文,该上下文被限制在某个队列中。我可以通过[managedObjectContext objectWithID:moID]
从子托管对象上下文中检索对象,但是当我尝试访问它的任何属性时(托管对象仍然是一个错误),我得到EXC_BAD_ACCESS
,堆栈跟踪显示_svfk_1
和@ 987654324@.
我知道在没有示例代码的情况下很难找出问题所在,但我希望有人能阐明可能的原因。谢谢。 =)
编辑:我尝试使用 existingObjectWithID:error:
而不是 Tom Harrington 建议的 objectWithID:
,现在它有时有效,但有时无效。我还在mergeChangesFromContextDidSaveNotification:
上经历了EXC_BAD_ACCESS
崩溃。我怀疑这可能是一个同步问题。如果我在一个上下文中编辑某些内容并保存,而在我的子上下文中编辑其他内容,这会导致问题吗?
编辑 2: 我弄清楚了为什么 existingObjectWithID:error: 有时但并非总是有效。托管对象 ID 确实是一个临时 ID(不应该 mergeChangesFromContextDidSaveNotification:
将其转换为永久 ID 吗?),所以我必须在传递 ID 之前调用 obtainPermanentIDsForObjects:error:
。但有时在子上下文的mergeChangesFromContextDidSaveNotification:
中我仍然会崩溃。这可能是什么原因?谢谢。
编辑 3:这是我的 MOC 层次结构的样子。
Persistent Store Coordinator
|
Persistent Store MOC
/ \
Main Queue MOC Child MOC (confinement)
我正在从主队列调用一个方法,该方法使用子 MOC(在另一个队列中)插入和更新一些托管对象,同时,我正在持久存储 MOC 中插入和更新托管对象。托管对象也可以同时更新、删除和插入到主队列 MOC 中。我将 Persistent Store Coordinator 的任何更改合并到主队列 MOC 和子 MOC。
还有一些问题:保存 MOC 会自动合并事物吗?如果 MOC 有待处理的合并请求,并且您在处理该合并请求之前保存,这会导致问题吗?
编辑 4:这是我初始化子 MOC 的方式。
dispatch_sync(_searchQueue, ^
_searchManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[_searchManagedObjectContext setParentContext:_persistentStoreManagedObjectContext];
[_searchManagedObjectContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
);
顺便说一句,我注意到只有当通知包含已删除的对象时,合并才会崩溃(EXC_BAD_ACCESS
)。
【问题讨论】:
哦:“假设objectID表示的持久存储中的数据存在—如果不存在,则返回的对象在您访问任何属性时(即触发故障时)会抛出异常)。”让我检查一下。 不,我在托管对象子类的prepareForDeletion
中添加了一个断点,但它从未被触发。所以我调用这个方法的时候,被管理的对象并没有被删除。
您是否使用 performBlock 与子 MOC 对话(我假设它不在主队列中)?
子 MOC 被限制在一个串行队列中,我使用该队列上的子 MOC 执行所有操作。
尝试用existingObjectWithID:error:
替换objectWithID:
,看看会发生什么。
【参考方案1】:
看来你还是太努力了。对于您的子 MOC,由于它位于串行队列中,因此请使用 NSPrivateQueueConcurrencyType
,并将其父 MOC 设置为您的主 MOC。
NSConfinementConcurrencyType
用于旧版配置。
【讨论】:
【参考方案2】:我找到了解决办法。在每次保存之前,我都会做[moc obtainPermanentIDsForObjects:[[moc insertedObjects] allObjects] error:&error]
。现在我不再遇到崩溃了。
我仍然对到底发生了什么有点模糊,但这是我的理解。当您保存新插入的对象时,只有在连接到持久存储协调器的 MOC 保存时,才会为它们分配一个永久 ID。现在,mergeChangesFromContextDidSaveNotification:
将永久 ID 向下传播(正如我所料),而其他一些操作恰好在合并之前发生,或者某处存在 Apple 错误。无论如何,事先获得永久 ID 解决了这个问题。
TL;DR Core Data+并发难。
【讨论】:
以上是关于尝试访问托管对象属性时的 EXC_BAD_ACCESS的主要内容,如果未能解决你的问题,请参考以下文章
Swift Core Data - 使用 NSManagedObject 子类访问获取的实体时出错
在 C# 4 中使用动态类型访问 javascript 对象的属性