3

まず第一に、この質問のより良いタイトルを見つけることができず申し訳ありません。

これは私自身を繰り返すことはできませんが、ユーザーに何度も起こったクラッシュです。HockeyApp(QuincyKit)を使用してクラッシュレポートを収集しています。したがって、この問題をデバッグすることはできません。コールスタックを読み取ることしかできません。しかし、私はそれを読んだ後、何が悪いのかについての手がかりを持っていません。途中で無関係な関数呼び出しをいくつか省略しました。

UI部分については、を使用NSFetchedResultsControllerしてデータを入力しUITableViewます。

Core Dataの部分では、iOS 5で新しく導入された親子MOCを使用しています。メインキューには親MOC、リソースフェッチキューには子MOCです。フェッチしたデータを処理した後、子MOCを保存します。子MOCを保存するとすぐに、変更はCore Dataによって自動的に親MOCにプッシュされ、FRCは変更を確認し、デリゲートを介してテーブルビューを更新する必要があります。次に、メインスレッドにコールバックして、追加のUI更新を行います。

[UITableView indexPathForRowAtPoint:]具体的には、どのように呼び出されたかは理解できます[NSFetchedResultsController objectAtIndexPath:]が、なぜそれが最終的に自分のエンティティに呼び出されたのinitWithEntity:insertIntoManagedObjectContext:か、なぜinitWithEntity:insertIntoManagedObjectContext:満たされない障害が発生するのかはわかりません。[NSFetchedResultsController objectAtIndexPath:]やるべきだと思いますが、ここfetchでやったのinsertです。

Exception Type:  SIGABRT
Exception Codes: #0 at 0x35e7e32c
Crashed Thread:  0

Application Specific Information:
*** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0xe62bdc0 <x-coredata://327F5799-CAB1-4086-8E75-0E87F0E19BF0/Status/p385>''

Last Exception Backtrace:
0   CoreFoundation                      0x355c888f __exceptionPreprocess + 162
1   libobjc.A.dylib                     0x3796f259 objc_exception_throw + 32
2   CoreData                            0x35f124f3 _PFFaultHandlerLookupRow + 1098
3   CoreData                            0x35f11d5b _PF_FulfillDeferredFault + 194
4   CoreData                            0x35f11c0b _sharedIMPL_pvfk_core + 38    
5   XXX                                0x0008a5c3 -[Tweet initWithEntity:insertIntoManagedObjectContext:] (Tweet.m:125)
6   XXX                                0x0003fd1b -[Status initWithEntity:insertIntoManagedObjectContext:] (Status.m:333)
7   CoreData                            0x35f0eded -[NSManagedObject(_NSInternalMethods) _initWithEntity:withID:withHandler:withContext:] + 164
8   CoreData                            0x35f0de07 -[NSManagedObjectContext(_NSInternalAdditions) _retainedObjectWithID:optionalHandler:withInlineStorage:] + 134
9   CoreData                            0x35f6b6eb _PFRetainedObjectIDCore + 330
10  CoreData                            0x35f67065 -[NSManagedObjectContext objectWithID:] + 88
11  CoreData                            0x35f32c09 _faultBatchAtIndex + 1352
12  CoreData                            0x35f31e73 -[_PFBatchFaultingArray objectAtIndex:] + 42
13  CoreData                            0x35f30a87 -[_PFMutableProxyArray objectAtIndex:] + 82
14  CoreData                            0x35fdd81d -[NSFetchedResultsController objectAtIndexPath:] + 204
16  XXX                                0x0009ebab -[TweetsViewController tableView:heightForRowAtIndexPath:] (TweetsViewController.m:581)
17  UIKit                               0x3304dab5 -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 2548
18  UIKit                               0x33067c3b -[UITableViewRowData rectForSection:] + 302
19  UIKit                               0x33125981 -[UITableViewRowData indexPathsForRowsInRect:] + 136
20  UIKit                               0x331258f1 -[UITableView indexPathsForRowsInRect:] + 52
21  UIKit                               0x33125889 -[UITableView indexPathForRowAtPoint:] + 28
22  XXX                                0x0009c193 -[TweetsViewController updateUI] (TweetsViewController.m:211)
25  XXX                                0x00111a6f __block_global_1 (ResourceFetcher.m:68)
26  libdispatch.dylib                   0x34458b87 _dispatch_barrier_sync_f_slow_invoke + 82
27  libdispatch.dylib                   0x34457ee7 _dispatch_main_queue_callback_4CF$VARIANT$mp + 194
28  CoreFoundation                      0x3559b2ad __CFRunLoopRun + 1268
29  CoreFoundation                      0x3551e4a5 CFRunLoopRunSpecific + 300
30  CoreFoundation                      0x3551e36d CFRunLoopRunInMode + 104
31  GraphicsServices                    0x371ba439 GSEventRunModal + 136
32  UIKit                               0x3302acd5 UIApplicationMain + 1080
33  XXX                                0x000044ff main (main.m:16)
34  XXX                                0x00003c50 start + 40

このクラッシュの問題を抱えているユーザーは通常、クラッシュの直前にテーブルビューがセル全体から空に変わるのを目にします。これは重要なヒントだと思いますが、すべてのデータが突然失われる理由は考えられません。データベースファイルを移動または削除するためのコードがありません。

4

2 に答える 2

3

まず、バグを探すときは、無関係な関数呼び出しはないので、おそらく呼び出しスタック全体で編集する必要があります...

オブジェクトを要求しているように見えますが(objectWithID呼び出しを参照)、管理対象オブジェクトコンテキストがオブジェクトを取得しようとすると、オブジェクトを見つけることができません。

これは通常、オブジェクトを削除している別のスレッドがあり、変更を適切に管理していない場合に発生します。

では、コアデータストアの状態を変更している他のスレッドはありますか?もしそうなら、それはおそらくあなたの犯人です。

Core Dataはそれほど難しくはありませんが、従わないと問題が発生するといういくつかのルールがあります。

まず、複数のスレッドからMOCにアクセスしないようにしてください。

次に、複数のスレッドが基になるストアを変更している場合は、親/子コンテキストを使用するか、DidSave通知を監視して、すべてのMOCSと適切に同期していることを確認してください。

編集

あなたはコメントしました:

はい、使用中の何かを削除する問題もあるのではないかと思います。しかし、まず最初に、initWithEntity:insertIntoManagedObjectContext:がここで呼び出される理由を知っていますか?

はい...オブジェクトをインスタンス化する必要があります。あなたのコールスタックを見てください、そしてあなたはそれを見ることができます...

UIがメインスレッドで更新しようとしています...

22  XXX  0x0009c193 -[TweetsViewController updateUI] (TweetsViewController.m:211)

したがって、UIKitはその機能を実行し、コントローラーへのデリゲートコールバックを作成します...

16  XXX  0x0009ebab -[TweetsViewController tableView:heightForRowAtIndexPath:] (TweetsViewController.m:581)

これにより、あなたが話しているFRC呼び出しが発生します...

14  CoreData  0x35fdd81d -[NSFetchedResultsController objectAtIndexPath:] + 204

そして、オブジェクトが必要になるので、フェッチされます...

10  CoreData  0x35f67065 -[NSManagedObjectContext objectWithID:] + 88

そうですね、CoreDataでさえオブジェクトをインスタンス化する必要があります。魔法のインターフェースはありません。管理対象オブジェクトを作成するための通常のAPIを呼び出します...明らかに「ステータス」タイプのオブジェクトをリクエストしています

6   XXX  0x0003fd1b -[Status initWithEntity:insertIntoManagedObjectContext:] (Status.m:333)

このオブジェクトには、「Tweet」タイプのオブジェクトが必要です。

5   XXX  0x0008a5c3 -[Tweet initWithEntity:insertIntoManagedObjectContext:] (Tweet.m:125)

そして、そのオブジェクトをインスタンス化する必要がある場合...オブジェクトが見つからないために失敗します。ですから、繰り返しになりますが、同期に論理エラーがあるのではないかと思います。オブジェクトを削除していて、他のコンテキストに適切に通知していないため、削除されたオブジェクトを参照している...または実際に保存されていないオブジェクトを参照している...または関係を変更したが適切に通知されていない他のコンテキスト。

いずれにせよ、データベースの変更方法を追跡すると、複数のスレッドで更新するための標準プロトコルに違反していることは間違いないと思います。

実際、あなたはあなたがそこにどのように到達しているかさえ見ることができます...

updateUIはGCDディスパッチキューから呼び出されています。ほとんどの場合、ResourceFetcherでは、メインスレッドを呼び出しています。そのコードでは、メインスレッドにそれ自体を更新するように依頼する前に、コンテキストを適切に保存し、すべての通知を行ったことを確認してください。

他のMOCからのDidSaveイベントをリッスンし、そのコンテキストから更新した後、UIを呼び出してそれ自体を更新することをお勧めします。

于 2012-06-02T23:34:56.647 に答える
2

最後に、それが私のバグなのかCore Dataのバグなのかはわかりませんが、クラッシュは修正されたと思います。

まず第一に、それはMOC間の同期とは何の関係もありません。

次に、yesinitWithEntity:insertIntoManagedObjectContext:は、オブジェクトがmocで最初にインスタンス化されたときに呼び出されます。オブジェクトが新しく作成されたか、リクエストでフェッチされたかは関係ありません。したがって、ドキュメントは誤解を招くようです。

contextがnilでない場合、このメソッドは[context insertObject:self]を呼び出します(これにより、awakeFromInsertが呼び出されます)。

フェッチのために呼び出されると、awakeFromFetchが呼び出されます。

バックトレースでわかるように、クラッシュはオーバーライドされたで発生しましたinitWithEntity:insertIntoManagedObjectContext:。十分に合理的initWithEntity:insertIntoManagedObjectContext:で、クラッシュの原因であることが判明しました。しかし、私はそれに悪いことは何もしなかったと思います。いくつかの永続属性を使用して、いくつかの非永続属性を初期化しました。

- (id)initWithEntity:(NSEntityDescription *)entity insertIntoManagedObjectContext:(NSManagedObjectContext *)context {
    self = [super initWithEntity:entity insertIntoManagedObjectContext:context];
    if (self) {
        // xxx_ is a persistent attribute while _xxx is the corresponding non-persistent attribute as its cache in memory only to reduce reading cost.
        _xxx = self.xxx_.unsignedIntegerValue;
    }
    return self;
}

最初の永続属性を読み取ったときに、実行できない例外がスローされることがありました。

私はいつもそれを知っています

このメソッドをオーバーライドすることはお勧めしません。代わりに、awakeFromInsertやawakeFromFetchをオーバーライドする必要があります(これらのメソッドに共通のロジックがある場合は、両方から呼び出される3番目のメソッドに組み込む必要があります)。このメソッドでカスタム初期化を実行すると、元に戻すおよびやり直し操作で問題が発生する可能性があります。

しかし、それが満たされない例外を引き起こすかどうかはわかりません。コアデータのバグですか?そうでなければ、私のコードの何が問題になっていますか?

于 2012-06-11T20:03:01.950 に答える