2013-04-05 8 views
6

私はコアデータを使用しており、バックグラウンドから再開した後にアプリケーションがクラッシュすることがあります。 NSManagedObjectサブクラスのプロパティにアクセスしようとすると、ブロックメソッド本体の内部で発生したクラッシュを特定しました。バックグラウンドから再開した後にコアデータ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にメッセージを返します。ブロック戻り、ラインself.calObject.note = noteTextアプリのクラッシュを実行します

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

明らかにブロックをスタックに置くことはできず、アプリケーションを再開してブロック内で定義されたものを続行することはできません。あるいは私はここで何か悪いことをしていますか?

編集:
*** 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]; 
    } 
+0

よりよく問題を理解することができるかもしれませんが、あなたはクラッシュメッセージを提供してもらえますか? –

+0

クラッシュ前のcalObjectのmanagedObjectContextとは何ですか?無名ですか? –

+0

ブロックをコールバックとして使用している途中でアプリケーションが終了して再開するときにのみ問題が発生します。他の状況では、私はかなり問題なくcalObjectを使って再開し続けます。何とかブロック内のブロックまたは「自己」が正しく保持されない可能性はありますか? – Oysio

答えて

2

私はあなたが非フォルト(EDIT2に見られるように)もはや(または決して持っていた)オブジェクトを持っているときに、この例外が発生しMagicalRecordsに慣れていないけど、...

ストアに存在します。
このいくつかのケースで起こるかもしれません:

  1. 別の文脈では、あなたがそれを挿入した店舗
  2. からそれを削除した、それのために永久的なIDを取得して:
    **
    それをリフレッシュします**親のコンテキストにのみ保存し、親をリセットして、現在のコンテキストでオブジェクトをリフレッシュします(またはメインコンテキストにフォールトとしてインポートします)。

私は忘れている、または知らない場合があります。

あなたのスタック構造を記述し、あなたのオブジェクトの状態/起源ができれば、我々は

2

トライもbackgoundの状態を保存してから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]; 
} 
0

私は魔法のレコードを使用したことがない、それはあなたが再構築されているように私には見えます、既存のアプリケーションが再びアクティブになると、コアデータスタック。あなたが本当にやりたいことが、applicationDidBecomeActive:(UIApplication *)の代わりにapplicationDidFinishLaunching:(UIApplication *)にコアデータをセットアップすることが想像されます。

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

問題は、古いコアデータスタックを参照するオブジェクトを持つと同時に、新しいコアデータスタックを作成したことです。

一般に、アプリケーションが起動すると、スタックを作成する必要があります。あなたは、アプリケーションが終了したときにスタックをきれいに落とそうとすることができます。しかし、単にバックグラウンドに行くときは、単にデータを保存し、アプリを単に再起動するだけで何もする必要はありません。

+0

これは例外を発生させず、コンテキストが保持されていない場合にのみオブジェクトを孤立させます(すべてのプロパティは無効になります) –

関連する問題