1

良い事実:

  • サーバーからデータをダウンロードし、Core Dataスレッドの制限を介してデータを保存します。バックグラウンドのMOCが保存されると、メインのMOCがマージされます。
  • すべての保存操作は問題ありません
  • また、MOCのマージは問題なく行われます。

私が探しているバグ:

  • NSFetchedResultsControllerを使用したUITableViewがアクティブな場合(つまり画面上)、保存が行われていると、AppDelegateのmergeChangesFromContextDidSaveNotification行に移動するSIGABRTでアプリがクラッシュします。
  • 最も奇妙な部分は、FRCのデリゲートがnilの場合、またはView Controllerであるが、FRCデリゲートメソッドを実装していない場合、クラッシュは発生せず、問題はないということです。 。しかし、デリゲートメソッドのいずれかを実装すると(コードが1行もなく、空の場合でも)、同じバグでアプリがクラッシュします。これは、メソッドが起動されていないことを意味します。問題は、これらのメソッド内のコードにはありません
  • 最も奇妙なパート2 (以下の更新2を確認):クラッシュはa[__NSCFNumber length]: unrecognized selector sent to instanceで発生し、CoreDataManagerでもAppDelegateクラスでも「length」プロパティを呼び出さない

目撃者:コンソール

<CoreDataManager.m:(338)> Saved data from server
<AppDelegate.m:(352)> Will merge
<CoreDataManager.m:(338)> Saved data from server
<AppDelegate.m:(355)> Did merge
<CoreDataManager.m:(338)> Saved data from server
<AppDelegate.m:(352)> Will merge
<AppDelegate.m:(355)> Did merge
<CoreDataManager.m:(338)> Saved data from server
<CoreDataManager.m:(338)> Saved data from server
<CoreDataManager.m:(338)> Saved data from server
<MyTableViewController.m:(134)> Fetched results controller did fetch 
<CoreDataManager.m:(338)> Saved data from server
<CoreDataManager.m:(338)> Saved data from server
<CoreDataManager.m:(338)> Saved data from server
<AppDelegate.m:(352)> Will merge
<CoreDataManager.m:(338)> Saved data from server
[__NSCFNumber length]: unrecognized selector sent to instance 0x13318050

いくつかのコード-MOCのマージ

- (void)managedObjectContextDidSave:(NSNotification *)notification
{
    NSManagedObjectContext *sender = (NSManagedObjectContext *)[notification object];

    if ((sender != self.managedObjectContext) &&
        (sender.persistentStoreCoordinator == self.managedObjectContext.persistentStoreCoordinator))
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            DebugLog(@"Will merge");
            [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
            DebugLog(@"Did merge");
        });
    }
}

アップデート1

Cocoaneticsのヒントに従って、誰が呼び出しているかを確認するためにNSNumberカテゴリを作成しましたlength以下のように表示され、 [__ NSCFNumber _fastCStringContents:]でクラッシュが発生しました:認識されないセレクターがインスタンスに送信されました。

ここに画像の説明を入力してください

アップデート2 ゾンビを有効にしても役に立たなかった=(

4

5 に答える 5

1

何ヶ月も何時間もかけて、ようやく解決策を見つけました。それは機能します。その理由についていくつかの意見を聞きたいです。

つまり、私が言ったように、保存は 100% 機能し、マージ通知も機能していました。NSFetchedResultsController デリゲートを nil に設定した場合、問題はありませんでした。ただし、デリゲートを UIViewController に設定すると、アプリがクラッシュしました。

おそらくデリゲートメソッドがトリガーされたときの私のコードが原因であると思いました。しかし、その前にアプリがクラッシュしました。そこで、Cocoanetics のヒントに従って、カテゴリを作成し、誰がlengthNSNumber オブジェクトへのメソッドを呼び出しているかを突き止めようとしました。その後- (BOOL)evaluateWithObject:(id)object;、クラッシュする前に NSPredicate が呼び出していることがわかりました。同じように、それをオーバーライドするカテゴリを作成しました。

@interface NSPredicate (PractiPredicate)
- (BOOL)evaluateWithObject:(id)object;
@end

@implementation NSPredicate (PractiPredicate)

- (BOOL)evaluateWithObject:(id)object
{
    NSLog(@"Evaluate was called. Object class %@", NSStringFromClass([object class]));
    MyManagedObject *myManagedObject = object;
    NSLog(@"Is fault? %d", myManagedObject.isFault);
    NSLog(@"myManagedObject changed and already have propertyA? %d", myManagedObject.propertyA != nil);
    return YES;
}

@end

驚いたことに、それは機能し、次のログが生成されました。

評価が呼び出されました。オブジェクト クラス MyManagedObject

過失ですか?0

myManagedObject が変更され、既に propertyA がありますか? 1

「Is fault?」と印刷することにしました。この混乱は NSManagedObject の障害に関連していると思ったからですが、印刷されたものはそうではありません。

コメントに対する質問: ここでこの問題が発生した原因は何だと思いますか?

于 2013-01-08T14:36:53.403 に答える
1

他の MOC からの通知のみを監視していることを確認してください。そこに保存すると、別のそのような通知がトリガーされ、オブジェクトが ARC によって解放されたため、1 回または 2 回の反復後に失敗する無限ループに陥る可能性があります。

于 2012-11-08T12:28:26.377 に答える
1

あなたはメモリの問題のように聞こえます。ARC 所有権修飾子を確認し、NSZombies を有効にします。NSZombies を有効にすると、時期尚早にリリースされたオブジェクトを絞り込むのに役立ちます。

ゾンビを有効にすると、代わりに「割り当て解除されたインスタンスに送信されたメッセージ」が表示されます。どのオブジェクトが時期尚早にリリースされたかを確認し、質問を更新してください。

于 2012-11-08T12:43:19.283 に答える
0

ほとんどの場合、問題は投稿したコードにあるのではなく、フェッチされた結果コントローラー デリゲートの変更を処理する方法にあります。それらはマージによってトリガーされているだけです。

于 2012-11-08T12:46:16.023 に答える
0

私は同じ問題を抱えていましたが、私の場合、クラッシュの理由が不適切な述語であることがわかりました。次のような述語がありました。

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"attribute > 0"];

attribute は文字列でした。次のように修正しました。

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"attribute.length > 0"];

今、私のコードは正常に動作しています。これもクラッシュの原因になる可能性があるため、コード内のすべての述語を確認してください。

于 2014-09-19T05:06:01.450 に答える