Core data 如果与dispatch_async一起使用,CoreData获取会崩溃

Core data 如果与dispatch_async一起使用,CoreData获取会崩溃,core-data,nsfetchedresultscontroller,objective-c-blocks,grand-central-dispatch,Core Data,Nsfetchedresultscontroller,Objective C Blocks,Grand Central Dispatch,我有一个核心数据应用程序,如果我在viewdiload中执行如下获取操作,它运行时不会崩溃: - (void) performCoreDataFetch { NSError *error; if (![[self fetchedResultsController] performFetch:&error]) { exit(-1); // Fail } } - (void)viewDidLoad { [super viewDidLoad]

我有一个核心数据应用程序,如果我在
viewdiload
中执行如下获取操作,它运行时不会崩溃:

- (void) performCoreDataFetch {
   NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) {
        exit(-1);  // Fail
    }
 }

- (void)viewDidLoad {
    [super viewDidLoad];
    [self performCoreDataFetch];
}
- (NSFetchedResultsController *)fetchedResultsController {
    if (fetchedResultsController != nil) {
        return  fetchedResultsController;
    }

    // Create and configure a fetch request with the Organization entity
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    request.entity = [NSEntityDescription entityForName:@"Organization" inManagedObjectContext:managedObjectContext];
    request.fetchBatchSize = 20;

    // create sortDescriptor array
    NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
    NSArray *sortDescriptorArray = [NSArray arrayWithObjects:nameDescriptor, nil];
    request.sortDescriptors = sortDescriptorArray;

    NSPredicate *predicate = nil;

    predicate = [NSPredicate predicateWithFormat:@"state LIKE %@", filterByState];
    [request setPredicate:predicate];

    // Create and initialize the fetchedResultsController
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc ] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:@"uppercaseFirstLetterOfName" cacheName:nil];

    self.fetchedResultsController = aFetchedResultsController;
    fetchedResultsController.delegate = self;

    // Memory management
    filterByState = nil;
//    [sortDescriptorArray release];
    [nameDescriptor release];
//    [predicate release];
    [request release];
    [aFetchedResultsController release];

    return fetchedResultsController;

}
上述执行获取的方法唯一的问题是,如果要返回的数据很大,它会将应用程序冻结几秒钟(但每次都会返回正确的结果而不会崩溃),因此为了避免这种情况,我决定使用dispatch_async(代码如下所示)并在其中调用
[self-performCoreDataFetch]

但如果我在viewDidLoad中的dispatch_sync中运行相同的[self-performCoreDataFetch],如下所示:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self performCoreDataFetch];
        dispatch_async(dispatch_get_main_queue(), ^{
           [self.tableView reloadData];
        });
    });
在dispatch\u async中调用
[self-performCoreDataFetch]
会使应用程序随机崩溃,并说“
-[NSFetchRequest fetchLimit]:发送到解除分配实例的消息

我的fetchedResultsController方法如下所示:

- (void) performCoreDataFetch {
   NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) {
        exit(-1);  // Fail
    }
 }

- (void)viewDidLoad {
    [super viewDidLoad];
    [self performCoreDataFetch];
}
- (NSFetchedResultsController *)fetchedResultsController {
    if (fetchedResultsController != nil) {
        return  fetchedResultsController;
    }

    // Create and configure a fetch request with the Organization entity
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    request.entity = [NSEntityDescription entityForName:@"Organization" inManagedObjectContext:managedObjectContext];
    request.fetchBatchSize = 20;

    // create sortDescriptor array
    NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
    NSArray *sortDescriptorArray = [NSArray arrayWithObjects:nameDescriptor, nil];
    request.sortDescriptors = sortDescriptorArray;

    NSPredicate *predicate = nil;

    predicate = [NSPredicate predicateWithFormat:@"state LIKE %@", filterByState];
    [request setPredicate:predicate];

    // Create and initialize the fetchedResultsController
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc ] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:@"uppercaseFirstLetterOfName" cacheName:nil];

    self.fetchedResultsController = aFetchedResultsController;
    fetchedResultsController.delegate = self;

    // Memory management
    filterByState = nil;
//    [sortDescriptorArray release];
    [nameDescriptor release];
//    [predicate release];
    [request release];
    [aFetchedResultsController release];

    return fetchedResultsController;

}

如果对fetchedResultsController执行提取,则核心数据不是线程安全的。这是有道理的,因为fetchedResultsController是UI的数据源。与其执行提取,不如将fetchedResultsController设置为
nil
,然后重新加载tableView。

如果对fetchedResultsController执行提取,则核心数据不是线程安全的。这是有道理的,因为fetchedResultsController是UI的数据源。不要执行提取,而是将fetchedResultsController设置为
nil
,然后重新加载tableView。

核心数据不是线程保存的。更确切地说,NSManagedObjectContext不是save。所有NSManagedObject都属于特定的NSManagedObject上下文,它们不能互换

在IOS 5之前,你需要使用非常复杂的方法。基本上每个线程都需要自己的NSManagedContext

IOS5之后,您可以执行以下操作:

__managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
那你就可以了

[__managedObjectContext performBlock ^{
    //Some really long operation
}]
在非主线程的任何线程上


这将在不同的线程上完成,但是以线程保存的方式。基本上,核心数据会将您的操作放入队列,它会逐个执行,并为每个操作锁定managedObjectContext。

核心数据不是线程保存。更确切地说,NSManagedObjectContext不是save。所有NSManagedObject都属于特定的NSManagedObject上下文,它们不能互换

在IOS 5之前,你需要使用非常复杂的方法。基本上每个线程都需要自己的NSManagedContext

IOS5之后,您可以执行以下操作:

__managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
那你就可以了

[__managedObjectContext performBlock ^{
    //Some really long operation
}]
在非主线程的任何线程上


这将在不同的线程上完成,但是以线程保存的方式。基本上,核心数据会将您的操作放入队列中,它会逐一执行,并锁定每个操作的managedObjectContext。

您想实现什么?您不必自己调用
performFetch
方法……没有performFetch,我不知道执行核心数据提取的其他方法。您想实现什么?如果延迟初始化获取的结果控制器,则获取将在那里完成,而无需自己调用
performFetch
。同样,您想用fetch做什么?下面是我想做的:如果您查看我的fetchedResultsController方法内部,就会发现有一个谓词参数“filterByState”。此变量通过其他tableViewController传递到此UITableViewController。基于该谓词,此fetchedResultsController返回的数据集每次都不同。如果这还不清楚,请告诉我。你想完成什么?您不必自己调用
performFetch
方法……没有performFetch,我不知道执行核心数据提取的其他方法。您想实现什么?如果延迟初始化获取的结果控制器,则获取将在那里完成,而无需自己调用
performFetch
。同样,您想用fetch做什么?下面是我想做的:如果您查看我的fetchedResultsController方法内部,就会发现有一个谓词参数“filterByState”。此变量通过其他tableViewController传递到此UITableViewController。基于该谓词,此fetchedResultsController返回的数据集每次都不同。如果还不清楚,请告诉我。您是说在我的nsfetchedResultsController方法中,我应该始终首先将fetchedResultsController设置为nil?否。当您需要更新表时,您可以将其设置为
nil
。表更新将自动调用您的
fetchedResultsController
方法,该方法将惰性地创建一个新方法。(看看这个方法,看看它是如何工作的。)你是说在我的nsfetchedResultsController方法中,我应该总是首先将fetchedResultsController设置为nil?不是。当你需要更新表时,你可以将它设置为
nil
。表更新将自动调用您的
fetchedResultsController
方法,该方法将惰性地创建一个新方法。(查看该方法并了解其工作原理。)