6

我正在使用核心数据,发现从后台恢复后应用程序有时会崩溃。当我尝试访问子类上的属性时,我已经确定了在块方法体内发生的崩溃NSManagedObject

我有一个包含NSManagedObject对子类的引用的属性。

@property(nonatomic,strong) CalItem *calObject;

为了重现崩溃,我首先需要调用子 viewController( NoteViewController) 并传递一个块 ( NoteTextBlock)。

NoteViewController *noteViewController = [[NoteViewController alloc]initWithNote:self.calObject.note NoteTextBlock:^(NSString *noteText) {
                    self.calObject.note = noteText;  //crashing here
                }];

然后将应用程序发送到后台并恢复它。之后在 NoteViewController 中,我将向调用 viewController 返回一条消息。

if (self.noteTextBlock)
{
 self.noteTextBlock(trimmedString);
}

当块返回并self.calObject.note = noteText执行该行时,应用程序崩溃。

所以显然你不能在堆栈上放一个块,完全恢复应用程序,然后继续块内定义的内容?或者我只是在这里做错了什么?

编辑:
*** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0xb253100 <x-coredata://C2304B7C-7D51-4453-9993-D33B9113A7A5/DTODay/p57>''

该块在子视图控制器中定义如下:

@property(nonatomic, copy)NoteTextBlock noteTextBlock;

Edit2
这是我在崩溃的行上设置断点时得到的。
(lldb) po self.calObject
$2 = 0x0b4464d0 <DTODay: 0xb4464d0> (entity: DTODay; id: 0xb489d00 <x-coredata://C2304B7C-7D51-4453-9993-D33B9113A7A5/DTODay/p57> ; data: <fault>)

我正在使用 MagicalRecord 库来管理所有核心数据的东西。

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if ([NSManagedObjectContext MR_defaultContext] == nil
        || [NSManagedObjectModel MR_defaultManagedObjectModel] == nil
        || [NSPersistentStoreCoordinator MR_defaultStoreCoordinator] == nil
        || [NSPersistentStore MR_defaultPersistentStore] == nil
        )
    {
        //coming back from background, re-init coredata stack
        [MagicalRecordHelpers setupCoreDataStackWithAutoMigratingSqliteStoreNamed:DBNAME];
    }
4

3 回答 3

2

尝试在后台保存状态,然后在 AppDelegate.m 中恢复唤醒状态

    - (void)applicationDidEnterBackground:(UIApplication *)application {
        /*
         Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
         Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
         */
        [MagicalRecord cleanUp]; 
}





   - (void) applicationDidBecomeActive:(UIApplication *)application {
        /*
         Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
         */
        [MagicalRecord setupCoreDataStackWithStoreNamed:DBNAME]; 
}
于 2013-04-11T14:38:32.527 回答
2

我不熟悉MagicalRecords,但是...

当您有一个在商店中不再存在(或从未存在过)的无故障(如在 Edit2 中看到的)对象时,会引发此异常。
这可能在以下几种情况下发生:

  1. 另一个上下文已将其从商店中删除
  2. 您已插入它,为其获取了永久 id,并且:
    ** 刷新它
    ** 保存它(但仅限于父上下文),重置父对象,并刷新当前上下文中的对象(或将其作为错误导入到您的主要背景),见objectWithID:

可能还有其他我忘记或不知道的情况。

如果您可以描述您的堆栈结构和您的对象状态/来源,我们可能能够更好地理解问题

于 2013-04-14T05:39:35.630 回答
0

我从未使用过 Magical Record,但在我看来,当应用程序再次激活时,您正在重建现有的 Core Data 堆栈。我想你真正想做的是设置核心数据applicationDidFinishLaunching:(UIApplication *)而不是applicationDidBecomeActive:(UIApplication *).

前者只会在应用程序启动时设置堆栈,而后者将在每次应用程序“唤醒”时重新设置堆栈。

问题是您随后创建了一个新的 Core Data 堆栈,同时拥有引用旧 Core Data 堆栈的对象。

通常,当应用程序启动时,您希望创建堆栈。当应用程序终止时,您可以尝试干净地取下堆栈。但是,当它只是进入后台时,您应该简单地保存数据,然后在重新激活应用程序时您真的不需要做任何事情。

于 2013-04-14T03:29:45.047 回答