Search code examples
cocoagrand-central-dispatchnsoutlineview

UI refresh, NSOutlineView reloadData and recursive methods


I populate a NSOutlineView reading a directory recursively. After a directory and its subdirectories are read I refresh the outline calling reloadData inside a dispatch like shown below

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

The method above is called from inside a dispatch to have the UI reactive

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

The problem is that sometimes dispatch_async(dispatch_get_main_queue(), ...) is called while subdirectories is reading (it's async at all!) and app crashes

If I use dispatch_sync(dispatch_get_main_queue(), ...) (note the sync version) the outline is drawn always correctly but it is very very slooooow so the question is:

how can I rearrange the code to be as fast as possible and wait that dispatch_[a]sync(dispatch_get_main_queue(), ...) has finished?


Solution

  • It sounds like the problem is that while some internal stuff is executing in one thread, your model is in an inconsistent state which reloadData can't properly handle.

    Are you adding directory entries to their parent directory before they're sufficiently set up?