我正在开发一款使用 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 场景转换有时是在 main\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 处理,动画也能顺利运行而不会卡住。
最佳答案
我已经设法解决了这个问题!
创建一个普通方法,您将调用 progressHUD 并调用第二个
创建第二种方法,您可以在其中执行耗时的操作(加载 View )
在主线程上执行该方法
示例:
-(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
}
希望对您有所帮助。
关于ios - 当主线程被阻塞时,MBProgressHUD 没有及时显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25548625/