6

コア データを使用していますが、バックグラウンドから再開した後にアプリがクラッシュすることがあります。NSManagedObjectサブクラスのプロパティにアクセスしようとすると、ブロック メソッド本体内で発生するクラッシュを特定しました。

NSManagedObjectサブクラスへの参照を保持するプロパティがあります。

@property(nonatomic,strong) CalItem *calObject;

クラッシュを再現するには、最初にNoteViewControllerブロック ( ) を渡して子 viewController( ) を呼び出す必要があり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>''

ブロックは、子 viewController 内で次のように定義されます。

@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 lib を使用して、すべてのコア データを管理しています。

- (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 に答える
0

Magical Record を使用したことはありませんが、アプリケーションが再びアクティブになったときに、既存の Core Data スタックを再構築しているように見えます。あなたが本当にやりたいことは、のapplicationDidFinishLaunching:(UIApplication *)代わりにCore Data をセットアップすることだと思いますapplicationDidBecomeActive:(UIApplication *)

前者はアプリの起動時にのみスタックをセットアップしますが、後者はアプリが「起動」するたびにスタックを再セットアップします。

問題は、古い Core Data スタックを参照するオブジェクトを持っている間に、新しい Core Data スタックを作成したことです。

通常、アプリの起動時にスタックを作成します。アプリの終了時に、スタックを完全に削除することを試みることができます。ただし、バックグラウンドになるだけの場合は、データを保存するだけでよく、アプリを再起動するだけで何もする必要はありません。

于 2013-04-14T03:29:45.047 に答える