1

Core Data で NSUndoManager を使用している iPad アプリがあります。数回元に戻す/やり直すと、ある程度再現可能なバグがあることを除いて、通常はうまく機能します。私はメインスレッドでのみ作業しています (少なくとも、MagicalRecords がセカンダリスレッドで NSManagedObject を使用するのを無効にしました。コンテキストへの NSManagedObject の挿入を元に戻したりやり直したりしようとすると、常に問題が発生します。

だから私はこのようなものを持っています:

if (!self.undoManager.isUndoing && !self.undoManager.isRedoing) 
{
    [self.undoManager undo];   
}
else 
{
    NSLog(@"gotcha!");
}

そして数回後、次の例外が発生します。これはセカンダリ スレッドで発生するため、Core Data がバックグラウンドで何かを実行していると思われます。

CoreData: error: Serious application error.  Exception was caught during Core Data
change processing.  This is usually a bug within an observer of 
NSManagedObjectContextObjectsDidChangeNotification.  _registerUndoObject:: NSUndoManager 
0xcea2d60 is in invalid state, must begin a group before registering undo
with userInfo (null) 2012-07-25 15:42:26.850 TT[3972:3c07] *** Terminating app due to 
uncaught exception 'NSInternalInconsistencyException', reason: '_registerUndoObject::
NSUndoManager 0xcea2d60 is in invalid state, must begin a group before registering undo

時々私はEXEC_BAD_ACCESSも取得していますが、それ以外の場合は上記の例外だけです。

何がこれを引き起こしているのでしょうか?

編集:ムンディの状況を明確化(コメントを参照)

4

2 に答える 2

0

私のクラッシュをすべて止めた解決策は次のとおりです。Magical Records はデフォルトで privateQueue 同時実行を使用しているようです。コードがそのスレッドセーフでない場合、うまくいかないと思います。私がしたことは、次のメソッドの NSPrivateQueueConcurrencyType から NSMainQueueConcurrencyType に変更することです。

+ (NSManagedObjectContext *) MR_contextWithoutParent;
{
    NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
return context;
}

ここで機能する別の詳細も見つけました: Core Data deleteObject: 属性を nil に設定します

私がしなければならなかったことは、管理オブジェクトを追加/削除する前に、管理オブジェクトのコンテキストを保存することでした。ちょっと奇妙で非効率的ですが、多くの手間を省きます。

于 2012-07-27T02:29:58.670 に答える
0

管理対象オブジェクトの挿入を元に戻す標準的な方法は、

[self.managedObjectContext deleteObject:theManagedObject];
// If you have saved already, you would need to save again.

元に戻すメカニズムを使用する必要はありません。このように、コードは次のようになります

  • はるかに読みやすく(やりたいことを明示的に言っている)、
  • エラーが発生しにくくなります(より複雑な API による予期しないイベントは発生しません)。
于 2012-07-26T16:29:13.907 に答える