Core Data 没有触发 NSManagedObject 实例的错误作为应用程序委托的属性
Posted
技术标签:
【中文标题】Core Data 没有触发 NSManagedObject 实例的错误作为应用程序委托的属性【英文标题】:Core Data not firing fault for an NSManagedObject instance as property on app delegate 【发布时间】:2013-07-25 20:14:13 【问题描述】:我将登录用户的数据从服务器导入一个名为“用户”的核心数据实体。我还将这个特定用户对象的引用保存到我的 AppDelegate(作为属性)上,以便我可以在我的应用程序的其他地方访问它。我面临的问题是,当我推送另一个视图控制器并尝试访问 appdelegate.loggedInUser.id 时,我看到“id”为 nil。调试器为对象显示了这个:
$24 = 0x0b28ad30 <User: 0xb28ad30> (entity: User; id: 0xb261160 <x-coredata:///User/tC48E8991-B8A6-4E68-9112-93F9F21DB5382> ; data: <fault>)
我的理解是,当我尝试访问该对象的某个属性时,Core Data 框架会触发错误。我很困惑为什么我在这种情况下访问用户的“id”属性没有触发错误?
编辑:
这是创建和使用loggedInUser对象的方法:
//method to get bgContext
+(NSManagedObjectContext *)getContextOnBgWithParentSetToMainMOC
NSManagedObjectContext *tmpContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[tmpContext setParentContext:[Utils getAppDelegate].managedObjectContext];
return tmpContext;
//in App Delegate
NSManagedObjectContext *bgContext = [NSManagedObjectContext getContextOnBgWithParentSetToMainMOC];
self.loggedInUser = [User importFromObject:loggedInUserData inContext:bgContext completionBlock:^(NSManagedObjectContext *theContext, NSManagedObject *theManagedObjectWithValuesImported) ];
//In User.m file
+ (User *)importFromObject:(NSDictionary *)dictionary inContext:(NSManagedObjectContext *)context completionBlock:(TemporaryContextImportReturnBlock)block
if ( !context )
context = [NSManagedObjectContext getContextOnBgWithParentSetToMainMOC];
NSManagedObjectContext *localContext = context;
User *newUserEntity = [NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:localContext];
NSArray *emailsArray = [dictionary objectForKey:@"emails"];
NSString *emailsString = @"";
if ([emailsArray count] > 0)
emailsString = [emailsArray componentsJoinedByString:@","];
newUserEntity.emails = emailsString;
newUserEntity.id = [dictionary objectForKey:@"id"];
newUserEntity.n = [dictionary nonNullObjectForKey:@"n"];
return newUserEntity;
//Access in one of the view controllers
User *loggedInUser = [Utils getAppDelegate].loggedInUser;
// loggedInUser.id /*nil*/
【问题讨论】:
您能否描述一下您用于 (a) 创建此用户,然后 (b) 访问它的过程,您在哪里看到 nilid
?这是一个临时对象 ID,因此看起来您正在使用保存对象之前的托管对象 ID。
@TomHarrington:用您询问的信息编辑了原始问题!
什么是bgContext
,它是如何创建的?是后台线程吗?
@Wain:已编辑。谢谢!
你实际上并没有在这里使用线程,你也没有使用performBlock:
。
【参考方案1】:
我也有同样的问题。事实证明,根据引用 Apple docs 的 this answer,NSManagedObject
确实不像您所期望的那样强烈引用其 NSManagedObjectContext
。我怀疑如果你检查你的对象时它没有正确触发错误[myObject managedObjectContext] == nil
。
我不知道这里有哪些最佳做法。显而易见(但可能很困难)的解决方案是找出您的 MOC 被释放的原因。作为替代方案,虽然我不确定这样做是否安全,但您可以保留每个 NSManagedObject
实例的 MOC。 (我对打开的here 有疑问。)
【讨论】:
谢谢你。我有一个“edit-nsmanagedobject-viewcontroller”,我会在准备 segue 时将 NSManagedObject 传递给它。当我想将更改发送到我的 backned 时,这个对象变成了错误,我不再知道它的 id。在初始化期间保留指向其上下文的指针可以防止这种情况发生。【参考方案2】:确保你不打电话
[managedObjectContext reset];
某处。来自 Apple 文档:
将接收器返回到其基本状态。 所有接收者管理的对象都被“遗忘”了。如果使用此方法,则应确保同时丢弃对使用接收器获取的任何托管对象的引用,因为之后它们将无效。
那些“孤立的”托管对象的 managedObjectContext 属性将变为 nil,它们将无法再触发故障。
【讨论】:
链接到苹果文档 vilém 谈到:developer.apple.com/documentation/coredata/…以上是关于Core Data 没有触发 NSManagedObject 实例的错误作为应用程序委托的属性的主要内容,如果未能解决你的问题,请参考以下文章
Core Data 使用多个上下文中的新对象从后台线程订购一对多关系保存
为啥在 Core Data container.performBackgroundTask() 之后不触发 tableView.reloadData()