0

発生するエラーは次のようなものです。

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_CDSnapshot_Widget_ unlockObjectStore]: unrecognized selector sent to instance 0x1c5a4350'

Widgetクラスがそのセレクターに送信される場合もあれば、__ NSCFStringである場合もあり、クラッシュが発生する場合もあります。

[NSManagedObjectContext unlockObjectStore]: message sent to deallocated instance 0x1ec658c0

問題が発生している場所を絞り込んだと思いますが、このコードが原因で問題が発生する理由がわかりません。データアクセスクラスの構造例は次のとおりです。

// DataController.m
static NSPersistentStoreCoordinator     *_persistentStoreCoordinator;
static NSManagedObjectModel             *_managedObjectModel;
static NSManagedObjectContext           *_mainManagedObjectContext;

@implementation DataController
- (NSManagedObjectContext *) privateManagedObjectContext {
    return [DataController buildManagedObjectContextForConcurrencyType:NSPrivateQueueConcurrencyType];
}

- (NSManagedObjectContext *) defaultManagedObjectContext {
    return [self managedObjectContextForConcurrencyType: self.defaultConcurrencyType];
}

- (NSManagedObjectContext *) managedObjectContextForConcurrencyType: (NSManagedObjectContextConcurrencyType) type {
    if (type == NSMainQueueConcurrencyType)
        return [self mainManagedObjectContext];
    else if (type == NSPrivateQueueConcurrencyType)
        return [self privateManagedObjectContext];

    return nil;
}

// calling _dataController.defaultManagedObjectContext from within the Widgets class
// essentially calls this method for a new context using NSPrivateQueueConcurrencyType as 
// the type parameter
+ (NSManagedObjectContext *) buildManagedObjectContextForConcurrencyType: (NSManagedObjectContextConcurrencyType) type {
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType: type];
    [context setUndoManager: nil];
    [context setMergePolicy: NSMergeByPropertyObjectTrumpMergePolicy];
    [context setPersistentStoreCoordinator: _persistentStoreCoordinator];
    return context;
}

@end

とウィジェットクラス

// Widgets.m
static DataController *_dataController;

@implementation Widgets
+ (void) initialize {
    _dataController = [[DataController alloc] init];
}

+ (NSArray *)certainWidgets {
    return [self certainWidgetsInManagedObjectContext:_dataController.defaultManagedObjectContext];
}

+ (NSArray *) certainWidgetsInManagedObjectContext: (NSManagedObjectContext *) context {
    // boiler plate CoreData fetching code
}
@end

これは、ウィジェットをフェッチするために使用されるコードの例です

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    for (Widget *w in [Widgets certainWidgets]) {
        if ([w.isValid intValue]) {
            // do something extraoridarily fantastic with the widget
        }
    }
});

これは、Xcode 4.6、リリースモード(デバッグではない)でのみ発生します。Xcode 4.6のリリースノートには、何が起こっているのかについての手がかりとなるものは何もありません。

この問題は、データアクセスクラス(DataController)の構造と、Widgetsクラス内のすべてのデータアクセスを処理するためにクラスメソッドを使用しているという事実に関係していると思われます。私が疑う理由は、Widgetsクラスからクラスメソッドを削除して代わりにインスタンスメソッドにし、+ initializeメソッドを削除し、WidgetsクラスのインスタンスごとにNSManagedObjectContextを設定すると、問題が発生するように見えるためです。あちらへ。

明確にするために、私は問題を修正したと思いますが、上記の変更が問題を修正する理由を理解するまで、修正をプッシュすることに抵抗があります。ある種のメモリの問題や、私たちが理解していない悪いプログラミングパラダイムがあるようです。ポインタはありますか?

4

2 に答える 2

0

これは、CLang の最適化に関連するバグであることが判明しました。他にも同じ問題を抱えている人が何人か見つかりました。すべての最適化をオフにすると、問題が解決するようです。

これは、静的データ管理インスタンスを作成し、新しいスレッドを生成し、その静的インスタンスを使用して管理対象オブジェクト コンテキストを作成するときに発生します。

私たちの修正は、データ管理のパラダイムを再考することです。

于 2013-03-06T18:57:09.943 に答える
-1

アプリでこの画面を使用している場合、または複数回表示されて 2 回目にクラッシュする場合は、この画面でメモリ管理を確認してください。画面の複数のコピーをメモリに保持している場合がこれに該当する可能性があります。たとえば、通知センターの削除オブザーバーを確認してください。

于 2015-04-20T10:49:05.007 に答える