我們得到的錯誤是這樣的:奇怪的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中,釋放模式(不在Debug中)。我們沒有看到Xcode 4.6發行說明中的任何內容,它們會給我們提供有關正在發生的事情的線索。
我懷疑這個問題與我們如何構建數據訪問類(DataController)以及我們使用類方法處理Widgets類中的所有數據訪問有關。我懷疑的原因是,當我們從Widgets類中移除類方法並改爲使用實例方法時,擺脫了+ initialize方法,併爲Widgets類的每個實例設置了一個NSManagedObjectContext,問題似乎就此消失遠。
只是爲了澄清,我認爲我已經解決了這個問題,但我不太願意推出修復程序,直到我明白爲什麼上述修改能夠修復它。看起來好像存在着某種內存問題或者糟糕的編程範例,我們沒有注意到。任何指針?