视图不会立即显示

Posted

技术标签:

【中文标题】视图不会立即显示【英文标题】:View is not displayed immediately 【发布时间】:2014-01-01 12:22:22 【问题描述】:

我想要达到的目标:

使用以下行为创建带有一些自定义图标、标签等的处理屏幕。

    在窗口上添加视图,在删除之前不允许用户触摸应用程序中的任何内容。 (如处理/加载屏幕)

    当显示此视图时,所有其他操作(如添加子视图、执行 segue 等)应该正常工作,但在我的加载视图下方。

    希望方法 showProcessingScreen 在任何线程上工作(无论线程切换代码等应该在各自的显示/隐藏方法中)。

    应在调用相应方法后立即显示/删除。

代码:

-(void) showProcessingScreen

    dispatch_async(dispatch_get_main_queue(),
    ^
           UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:@"Main_iPhone" bundle:nil];
            processingScreen = [mystoryboard instantiateViewControllerWithIdentifier:@"loadingViewController"];

            UIWindow* mainWindow = [[UIApplication sharedApplication] keyWindow];
            [mainWindow addSubview: processingScreen.view];
            [mainWindow bringSubviewToFront:processingScreen.view];
   );




-(void) hideProcessingScreen

    dispatch_async(dispatch_get_main_queue(),
    ^
         [processingScreen.view removeFromSuperview];
   );

问题:

我希望上面的代码能够立即显示/隐藏加载屏幕。

- (IBAction)proceedBtnPressed:(id)sender

     [[GUIUtilities sharedObj] showProcessingScreen];
     //Some other code here

当我像上面那样调用 showProcessingScreen 时,处理屏幕大约需要 2-3 秒才能显示。 但是当我删除它下面的其他代码(//其他一些代码)时,它会立即显示屏幕。

我尝试过的:

    将代码放在 showProcessingScreen 中的其他方法中,并使用 performSelectorOnMainThread 在主线程上调用。 在后台调用 showProcessingScreen 并使用 performSelector 在主线程上执行显示代码。 这行得通

//代码

-(IBAction)proceedBtnPressed:(id)sender

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
    ^
        [[GUIUtilities sharedObj] showProcessingScreen];
        //Some other code here
     );

但我不想要 showProcessingScreen 之外的任何线程切换机制。

这是几乎在每个应用程序中都使用的常见屏幕。我在 xib 中使用了类似的代码,在我以前的应用程序中没有使用故事板等的自定义视图, 我知道这与线程有关,我在这里做错了什么?实现这一目标的最佳做法是什么? 任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

问题在于,当您调度时,您将加载视图的创建放在运行循环的末尾。无论您的“其他代码”是什么,都会阻塞主线程几秒钟。

如果您将此“其他代码”移至其他线程,这将解决您的问题。 (这个解决方案很理想。)

你也可以只有条件地切换到主线程,如果你从主线程调用加载视图,这将解决问题:

-(void) showProcessingScreen

    if (![NSThread isMainThread]) 
        [self performSelectorOnMainThread:@selector(showProcessingScreen) withObject:nil waitUntilDone:FALSE];
        return;
    
           UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:@"Main_iPhone" bundle:nil];
            processingScreen = [mystoryboard instantiateViewControllerWithIdentifier:@"loadingViewController"];

            UIWindow* mainWindow = [[UIApplication sharedApplication] keyWindow];
            [mainWindow addSubview: processingScreen.view];
            [mainWindow bringSubviewToFront:processingScreen.view];

【讨论】:

是的,这就是我之前写的方式。但它不起作用:(它曾经用于非基于故事板的视图。 你明白为什么它不工作了吗?看看我所说的将“其他代码”移动到后台线程。【参考方案2】:

无需添加拦截触摸事件的覆盖视图,您只需调用

– beginIgnoringInteractionEvents
– endIgnoringInteractionEvents

【讨论】:

不是我所问问题的解决方案,我需要自定义叠加视图,因为我想显示一些带有微调器、标签等的自定义视图 可以,但您不需要“拦截触摸事件”。【参考方案3】:

你可以试试这个:

- (void)doSomeOtherCode 

   //Some other code here


- (IBAction) showProcessingScreenAndDoSomeOtherCode:(id)sender

   [[GUIUtilities sharedObj] showProcessingScreen];
   [self performSelector:@selector(doSomeOtherCode) withObject:nil afterDelay:0.0];


- (IBAction)proceedBtnPressed:(id)sender

    [self showProcessingScreenAndDoSomeOtherCode:self];

它会起作用的。关于您的评论:

但我不想要 showProcessingScreen 之外的任何线程切换机制。

上述解决方案不会导致showProcessingScreen之外的任何线程切换。 performSelector 只会在事件循环队列中添加一个条目。

编辑:

如果你使用块,同样的结果可以通过:

dispatch_async(dispatch_get_main_queue(),
^
    [[GUIUtilities sharedObj] showProcessingScreen];
    dispatch_async(dispatch_get_main_queue(), ^
        //Some other code here
    );
 );

或:

dispatch_async(dispatch_get_main_queue(),
^
    [[GUIUtilities sharedObj] showProcessingScreen];
 );
dispatch_async(dispatch_get_main_queue(), ^
    //Some other code here
);

由于主队列是串行队列,showProcessingScreen 和“这里的一些其他代码”将被串行执行。

【讨论】:

感谢您的回答。是的,它有效,但我会从代码的不同部分调用 showProcessingScreen。然后我需要多次编写 doSomeOtherCode 之类的方法,并且在某些情况下 doSomeOtherCode 将需要一些参数。所以不适合我的情况。 查看我编辑的答案以解决您的第一个问题;至于第二个,那些参数是什么?如果您有参数,那么您的proceedBtnPressed 无法传递它们,那么您将如何处理呢? 不适合从嵌套代码调用 showProcessingScreen。而且我需要在我调用它的每个类中编写类似于 doSomeOtherCode 的方法。我想要一些机制,它可以让我在不接触其他代码的情况下展示它 我不确定我是否完全理解“嵌套代码”的含义,我认为它的意思是“块”。在这种情况下,请参阅我的编辑。

以上是关于视图不会立即显示的主要内容,如果未能解决你的问题,请参考以下文章

视图控制器不会立即关闭并呈现新的视图控制器

视图的隐藏过渡与显示过渡不同

在新视图中立即显示键盘[重复]

UIActivityViewController 对于某些用户会立即消失

调用 layoutIfNeeded 后视图未立即显示

UIAlertController 不会立即显示