主线程被阻止时,MBProgressHUD未按时显示

时间:2014-08-28 12:16:25

标签: ios multithreading uikit cocos2d-x mbprogresshud

我正在开发一款使用cocos2d-x的游戏,我在ipad 1等旧设备上遇到问题,因为大型场景需要花费大量时间才能加载。 所以场景转换可能需要几秒钟,因此我试图实现一个忙碌的"在加载新场景时场景转换之间的动画。 我使用IOS上的MBProgressHUD和android上的ProgressDialog实现了这个。 我决定不想立即开始显示这个动画,而是我可以安排动画在场景转换开始后1-2秒开始,这样在较新的设备上动画将根本不会显示。 最初我做的是这个:

- (void) showProgressDialog: (int) runWithoutDelay
    {
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(showProgressDialogAfterDelay) object:nil];
    shouldShow = YES;
    if (runWithoutDelay){
        [self showProgressDialogAfterDelay];
    }
   else{
       [self performSelector:@selector(showProgressDialogAfterDelay) withObject:nil   afterDelay:delay];
       }
   }

- (void) showProgressDialogAfterDelay
  {
   if (shouldShow){
       isShown = YES;
       [progressHUD show:YES];
   }

}

如果我通过场景转换部分,我只需将shouldShow标志设置为false并且不会启动动画。 问题是因为cocos2d-x场景转换是在主\ ui线程中完成的,有时而不是在2秒后调用show方法,它需要6-8秒才能被调用,有时它甚至在我设置后调用标志为假。 据我所知,这是因为performSelector(我也尝试过NSTimer)都是通过将调用放在线程运行循环队列中而在同一个线程上运行。 我需要像performSelectorInBackground那样需要延迟的东西,所以我尝试使用dispatch_after(尽管我仍然没有弄清楚如何取消它,因为我需要取消之前的计划,当我创建一个新计划时)这看起来更多准确地根据Xcode的日志,但即使日志说该方法在被安排后2秒正好被调用,时间将花费5-8秒来显示,有时根本不会显示。 据我所知,并纠正我,如果我错了,这是因为MBProgressHUD更改为UI必须发生在主\ UI线程上,所以即使我在后台线程上调用[ProgressHUD show:YES]实际更新UI被安排在主线程上以某种方式执行,并且由于它被卡在cocos2d-x上,它只在场景转换完成后才开始显示,而且为时已晚。

有什么方法可以解决这个问题吗?我可以以某种方式安排它以延迟开始但是在我想要的时候显示它吗?

我不明白的是,如果我毫不拖延地启动它,即使主线程忙于cocos2d-x处理,动画也能顺利运行而不会卡住。

1 个答案:

答案 0 :(得分:2)

我以某种方式解决了这个问题!

  1. 创建一个常规方法,您将调用progressHUD并调用第二个

  2. 创建第二种方法,用于执行耗时的工作(加载视图)

  3. 在主线程上执行该方法

  4. 样品:

    -(void)callHUD {
    
                [progressHUD show];
    
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    [self performSelectorOnMainThread:@selector(loadView) withObject:nil waitUntilDone:YES];
                    dispatch_async(dispatch_get_main_queue(), ^{
                [progressHUD dismiss];
        });
    });
    }
    
    -(void)loadView {
        //Perform your segue or transition which needs to load
    }
    

    希望能帮到你一点点。