UI刷新、NSOutlineView reloadData和递归方法

发布于 2024-12-07 04:20:31 字数 878 浏览 3 评论 0原文

我填充 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];
  }
}

从调度内部调用上面的方法以使 UI 响应

   - (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(),...)(注意同步版本)轮廓绘制总是正确的,但它非常非常慢,所以问题是:

我如何才能尽可能快地重新排列代码并等待dispatch_[a]sync(dispatch_get_main_queue(), ...)完成?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

水波映月 2024-12-14 04:20:31

听起来问题在于,虽然一些内部内容在一个线程中执行,但您的模型处于不一致的状态,reloadData无法正确处理。

您是否在充分设置目录条目之前将其添加到其父目录中?

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?

幻想少年梦 2024-12-14 04:20:31

虽然已经晚了,但看起来像这样编写 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];
        });
    }
}

Late to this one, but it seems like it would make a lot more sense to write your readDir: like this:

-(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];
        });
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文