Тупик в рутине - PullRequest
       29

Тупик в рутине

2 голосов
/ 27 марта 2012

Я застрял с моим первым GCD и первыми основными данными, используя приложение =)

два представления обращаются к одним и тем же данным (которые обрабатываются одним DAO).

если я подожду, пока текущее представление не завершит загрузку содержимого, при смене представления проблемы не возникнут.

однако: если я изменяю представление (на основе вкладок), когда один контроллер пытается извлечь данные из моей модели, новый контроллер пытается сделать то же самое, и потоки "сталкиваются", и мое приложение зависает.

замораживание происходит в этой строке кода моего DAO:

    NSArray *results = [managedObjectContext executeFetchRequest:fetch error:&error];    

reloadAllMonth() обращается к процедуре выборки моего DAO

как я загружаю данные в первый контроллер:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
                [self reloadAllMonth];

                dispatch_async(dispatch_get_main_queue(), ^(void) {                        
                    [self.allMonthTable reloadData];    
                });

во втором viewcontroller первое, что я делаю, это обновляю мой DAO, он, конечно, использует (помимо других) ту же самую процедуру извлечения, которую я вызывал ранее:

    [self.dataHandler updateData];

я пыталсяПока два подхода:

первый с использованием c-семафора:

-(NSArray *)fetchAllMonthExpenses{  
    //@return: array of all expenses in month (day & month type)


    NSNumber *monthNumber = [self getMonthNumber:[NSDate date]];
        NSEntityDescription *exp = [NSEntityDescription entityForName:@"Expense" inManagedObjectContext:managedObjectContext];
    NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
    [fetch setEntity:exp];
    [fetch setPredicate:[NSPredicate predicateWithFormat:@"month == %@",monthNumber]];
    NSError *error = nil;
    sem_wait(&isLoading);
    NSArray *results = [self.managedObjectContext executeFetchRequest:fetch error:&error];  
    sem_post(&isLoading);
    return results;

}

второй с использованием синхронизированной директивы

-(NSArray *)fetchAllMonthExpenses{  
    //@return: array of all expenses in month (day & month type)


    NSNumber *monthNumber = [self getMonthNumber:[NSDate date]];
        NSEntityDescription *exp = [NSEntityDescription entityForName:@"Expense" inManagedObjectContext:managedObjectContext];
    NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
    [fetch setEntity:exp];
    [fetch setPredicate:[NSPredicate predicateWithFormat:@"month == %@",monthNumber]];
    NSError *error = nil;
    @synchronized(self.class){
        NSArray *results = [self.managedObjectContext executeFetchRequest:fetch error:&error];  
        return results;
    }    
}

к сожалению, оба подхода не сработали, приложение зависает, что бы я ни делал.

поэтому мой вопрос: что я делаю не так (как я уже упоминал в первый раз, используя потоки), чего мне не хватает,где я должен смотреть?

это держаля занят в течение 2 дней, и я не могу обернуться вокруг него: /

1 Ответ

4 голосов
/ 27 марта 2012

NSManagedObjectContext и все NSManagedObjects внутри него не являются поточно-ориентированными.

Какой бы поток вы не использовали для создания контекста, это должен быть поток only , где вы делаете что-либо , относящееся к этому контексту. Даже просто чтение значений из одного из управляемых объектов должно быть выполнено в этом потоке , а не в любом другом потоке.

Если вам нужны два потока, которые работают с одной и той же базой данных, у вас есть два варианта:

  • используйте dispatch_sync() для мгновенного перехода в другой поток для выполнения всех операций чтения / записи над управляемыми объектами и / или контекстом

Или:

  • создайте второй NSManagedObjectContext в другом потоке для той же базы данных и синхронизируйте все изменения, сделанные в двух контекстах.

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

Для получения более подробной информации обратитесь к Руководству по программированию основных данных.

...