我的问题如下:我的UI中有三个按钮,它们将触发具有不同参数的相同获取请求。如果我按顺序按下这些按钮,但在每个按钮之间等待一两秒,一切正常。如果我更快地做到这一点,该应用程序将冻结。调试器显示了一个互斥锁。现在,我正在使用带有mainMOC和backgroundMOC的CoreData,我找不到我做错了什么以及如何解决我的问题。
我检查了类似的问题,但所有建议的解决方案对我都不起作用。 以下是我认为涉及此问题的代码:
@interface LooksDataSource ()
@property (nonatomic,strong) NSManagedObjectContext *mainContext;
@property (nonatomic,strong) NSManagedObjectContext *backgroundContext;
@property (nonatomic,strong) NSFetchedResultsController *fetchedResultsController;
@end
@implementation LooksDataSource
-(id) init {
@throw [NSException exceptionWithName:@"LooksDataSource exception" reason:@"please use initWithManagedObjectContext" userInfo:nil];
}
-(void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(id) initWithManagedObjectContext: (NSManagedObjectContext *) context {
self = [super init];
if (self) {
self.mainContext = context;
dispatch_async(dispatch_get_global_queue(0, 0), ^(){
self.backgroundContext = [[NSManagedObjectContext alloc] init];
self.backgroundContext.persistentStoreCoordinator = self.mainContext.persistentStoreCoordinator;
});
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(repoUpdated:) name:NSManagedObjectContextDidSaveNotification object:self.mainContext];
}
return self;
}
-(void) findLooksWithPredicate: (NSPredicate *) predicate {
if (![predicate isEqual:self.fetchedResultsController.fetchRequest.predicate]) {
[self performNewRequestwithPredicate:predicate];
}
else {
//return results of latest fetch
id <NSFetchedResultsSectionInfo> sectionZeroInfo = [self.fetchedResultsController sections][0];
NSMutableArray *objectIDsForResults = [NSMutableArray array];
for (NSManagedObject *aResult in [sectionZeroInfo objects]) {
[objectIDsForResults addObject:aResult.objectID];
}
dispatch_async(dispatch_get_main_queue(), ^{
//re-create the MOs referred to in objectIDsForResults in the "main" MOC
NSMutableArray *resultsOnMainMOC = [NSMutableArray array];
for (NSManagedObjectID *aResultID in objectIDsForResults) {
[resultsOnMainMOC addObject:[self.mainContext objectWithID:aResultID]];
}
NSArray *results = [NSArray arrayWithArray:resultsOnMainMOC];
[self.delegate looksDataSource:self
returnedResults:results];
});
}
}
感谢大家的帮助
答案 0 :(得分:1)
正如@Wain所说,目前还不清楚你在这里如何使用线程以及背景提取的位置。
有人说......
您创建背景MOC的方式不是线程安全的:
您创建使用线程限制并发类型的托管对象上下文
这意味着您必须在创建的线程上使用此上下文 ONLY
由于您使用GCD创建了此上下文,因此您不知道哪个线程创建了它,也不能让该线程保持活动状态。
问题的解决方案是@Wain所说的:对于您在后台发送的每个操作,创建一个受限的托管对象上下文,使用它,并在操作结束时确保您处理它:
dispatch_async(dispatch_get_global_queue(0, 0), ^(){
NSManagedObjectContext* context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = self.mainContext.persistentStoreCoordinator;
//Make the fetch and export results to main thread
});