CoreData Fetch Сбои при использовании с dispatch_async - PullRequest
0 голосов
/ 01 апреля 2012

У меня есть приложение с основными данными, которое работает без сбоев, если я выполняю выборку внутри viewDidLoad, например:

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

- (void)viewDidLoad {
    [super viewDidLoad];
    [self performCoreDataFetch];
}

Единственная проблема с вышеуказанным способом выполнения выборки состоит в том, что, если возвращаемые данные большие, приложение останавливается на несколько секунд (но возвращает правильный результат без сбоев каждый раз), поэтому, чтобы избежать этого, я решил использовать dispatch_async (код показан ниже) и вызывать [self performCoreDataFetch] внутри него.

Но если я запускаю этот же [self executeCoreDataFetch] внутри dispatch_sync в viewDidLoad , как показано ниже:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self performCoreDataFetch];
        dispatch_async(dispatch_get_main_queue(), ^{
           [self.tableView reloadData];
        });
    });

При вызове [self performCoreDataFetch] в dispatch_async происходит случайное падение приложения, говоря «-[NSFetchRequest fetchLimit]: message sent to deallocated instance»

Мой метод fetchedResultsController выглядит следующим образом:

- (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;

}

Ответы [ 2 ]

3 голосов
/ 01 апреля 2012

Данные ядра не являются поточно-ориентированными, если вы выполняете выборку для fetchedResultsController. Это имеет смысл, так как fetchedResultsController является источником данных вашего пользовательского интерфейса. Вместо того, чтобы выполнять выборку, установите ваш fetchedResultsController на nil и перезагрузите tableView.

1 голос
/ 08 октября 2012

Основные данные не сохраняются в потоке.Чтобы быть более точным, NSManagedObjectContext не сохраняется.Все NSManagedObject принадлежат определенному NSManagedObjectContext, и они не являются взаимозаменяемыми.

Перед IOS 5 вам нужно поставить действительно очень сложный метод.В основном каждый поток требует свой собственный NSManagedContext

После IOS5 вы можете сделать:

__managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

Затем вы можете сделать

[__managedObjectContext performBlock ^{
    //Some really long operation
}]

в любом потоке, который не является основным потоком.

Это сделает это в другом потоке, но в потоке сохранит его.В основном данные ядра помещают вашу операцию в очереди, и она будет выполнять ее одну за другой, блокируя управляемый объект для каждой операции.

...