2013-03-05 2 views
0

ошибка мы получаем что-то вроде этого:Странный Xcode 4.6 родственный ошибка

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, режим Release (не в Debug). Мы ничего не видим в примечаниях к выпуску Xcode 4.6, которые дадут нам ключ к тому, что происходит.

Я подозреваю, что проблема связана с тем, как мы структурировали наш класс доступа к данным (DataController) в сочетании с тем фактом, что мы используем методы класса для обработки всего доступа к данным в классе Widgets. Причина моего подозрения в том, что, когда мы удаляем методы класса из класса Widgets и вместо этого делаем им методы экземпляра, избавляемся от метода + initialize и настраиваем NSManagedObjectContext для каждого экземпляра класса Widgets, проблема, похоже, идет далеко.

Просто, чтобы уточнить, я думаю, что исправил проблему, но мне неудобно отталкивать исправление, пока я не пойму, почему вышеупомянутые изменения исправить. Похоже, что есть какая-то проблема с памятью или неправильная парадигма программирования, которую мы не улавливаем. Любые указатели?

ответ

0

Оказывается, это ошибка, связанная с оптимизацией CLang. Мы обнаружили, что некоторые другие люди испытывают ту же проблему. Кажется, что устранение всех отключений оптимизации устраняет проблему.

Это происходит для нас при создании экземпляра статического управления данными, создания нового потока и использования этого статического экземпляра для создания контекста управляемого объекта.

Наше решение состоит в том, чтобы пересмотреть нашу парадигму управления данными.

-1

Если вы используете этот экран над своим приложением, или он появляется несколько раз, то & падает во второй, чем проверяет управление вашей памятью на этом экране. Это может быть так, когда вы держите в памяти несколько копий экрана. Например, проверьте наблюдателя удаления центра уведомлений.