Обновление пользовательского интерфейса, NSOutlineView reloadData и рекурсивные методы - PullRequest
1 голос
/ 28 сентября 2011

Я заполняю NSOutlineView, читая каталог рекурсивно.После прочтения каталога и его подкаталогов я обновляю схему вызова reloadData внутри диспетчеризации, как показано ниже

-(void)readDir:(NSString*)path {
   dispatch_async(dispatch_get_main_queue(), ^{ \
      [outlineView reloadData];
   });

 //////////
 //// some internal stuff
 //////////

  NSArray* subs = [self getSubDirs:path];
  for (NSString* p in subs) {
      [self readDir:p];
  }
}

Вышеприведенный метод вызывается из диспетчеризации, чтобы пользовательский интерфейс реагировал

   - (void)startAll {
        dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
        dispatch_async(queue, ^{
           [self readDir:@"/"];
        });
   }

Проблема в том, что иногда dispatch_async (dispatch_get_main_queue (), ...) вызывается, когда подкаталоги читают (это вообще асинхронно!) И происходит сбой приложения

Если я использую dispatch_sync (dispatch_get_main_queue (), ..).) (обратите внимание на версию sync ) контур рисуется всегда правильно, но он очень запутанный, поэтому возникает вопрос:

как я могу изменить код так, чтобы он был максимально быстрым иподождать, пока синхронизация dispatch_ [a] (dispatch_get_main_queue (), ...) завершится?

Ответы [ 2 ]

3 голосов
/ 29 сентября 2011

Похоже, проблема в том, что пока some internal stuff выполняется в одном потоке, ваша модель находится в несовместимом состоянии, которое reloadData не может правильно обработать.

Вы добавляете записи каталога в их родительский каталог до того, как они будут достаточно настроены?

1 голос
/ 30 ноября 2012

Поздно, но кажется, что было бы гораздо разумнее написать readDir: так:

-(void)readDir:(NSString*)path {
   //////////
   //// some internal stuff
   //////////

    NSArray* subs = [self getSubDirs:path];
    for (NSString* p in subs) {
        [self readDir:p];
        // now refresh outline with newly acquired info and current data
        dispatch_sync(dispatch_get_main_queue(), ^{ \
          [outlineView reloadData];
        });
    }
}
...