我的问题如下:我的UI中有三个按钮,它们将使用不同的参数触发相同的提取请求。如果我按顺序按这些按钮,但每次之间等待一两秒钟,则一切正常。如果我做得更快,该应用程序将冻结。调试器显示了一个互斥锁。现在,我将CoreData与mainMOC和backgroundMOC一起使用,但找不到我做错了什么以及如何解决问题。

我已经检查了类似的问题,但是建议的所有解决方案都不适用于我。
这是我认为涉及此问题的代码:

@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];
        });
    }
}


感谢你的帮助

最佳答案

正如@Wain所说,目前尚不清楚您如何在此处使用线程以及在何处进行后台获取。

话虽如此 ...

创建后台MOC的方法不是线程安全的:
您创建使用线程限制并发类型的托管对象上下文。
这意味着您只能在创建该线程的线程上使用此上下文。
由于您使用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
});

关于ios - 多个提取请求导致应用程序卡住,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21800861/

10-11 02:35