2013-03-05 127 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中,释放模式(不在Debug中)。我们没有看到Xcode 4.6发行说明中的​​任何内容,它们会给我们提供有关正在发生的事情的线索。

我怀疑这个问题与我们如何构建数据访问类(DataController)以及我们使用类方法处理Widgets类中的所有数据访问有关。我怀疑的原因是,当我们从Widgets类中移除类方法并改为使用实例方法时,摆脱了+ initialize方法,并为Widgets类的每个实例设置了一个NSManagedObjectContext,问题似乎就此消失远。

只是为了澄清,我认为我已经解决了这个问题,但我不太愿意推出修复程序,直到我明白为什么上述修改能够修复它。看起来好像存在着某种内存问题或者糟糕的编程范例,我们没有注意到。任何指针?

回答

0

原来,这是一个与CLang优化相关的错误。我们发现一些其他人遇到同样的问题。关闭所有优化似乎解决了这个问题。

对于我们来说,创建一个静态数据管理实例,产生一个新线程,并使用该静态实例创建一个托管对象上下文时,情况就会发生。

我们的修补程序将重新考虑我们的数据管理范例。

-1

如果您在此应用上使用此屏幕,或者第二次出现&崩溃,请检查您在此屏幕上的内存管理。可能是这种情况,当你在内存中保存好几个屏幕副本。例如,检查通知中心删除观察者。