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

我想要达到的目标:

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

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

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

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

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

代码:

-(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 秒才能显示。 但是当我删除它下面的其他代码(//其他一些代码)时,它会立即显示屏幕。

我尝试过的:

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

//代码

-(IBAction)proceedBtnPressed:(id)sender
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
    ^{
        [[GUIUtilities sharedObj] showProcessingScreen];
        //Some other code here
     });
}

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

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

【问题讨论】:

    标签: ios objective-c storyboard uiwindow


    【解决方案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 的方法。我想要一些机制,它可以让我在不接触其他代码的情况下展示它
    • 我不确定我是否完全理解“嵌套代码”的含义,我认为它的意思是“块”。在这种情况下,请参阅我的编辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多