视图不会立即显示

时间:2014-01-01 12:22:23

标签: ios objective-c storyboard uiwindow

我想要实现的目标:

使用一些自定义图标,标签等创建处理屏幕,并具有以下行为。

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

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

  3. 希望方法showProcessingScreen能够在任何线程上工作(无论是哪种线程切换代码都应该在各自的show / hide方法中)。

  4. 在调用各自的方法后,应立即显示/删除。
  5. 代码:

    -(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在主线程上执行show code。
    3. 此作品
    4. //代码

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

      但我不想在showProcessingScreen之外使用任何线程切换机制。

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

3 个答案:

答案 0 :(得分:0)

你可以试试这个:

- (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和“此处的其他一些代码”将以串行方式执行。

答案 1 :(得分:0)

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

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

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

-(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 :(得分:0)

您可以直接调用

,而不是添加拦截触摸事件的叠加视图
– beginIgnoringInteractionEvents
– endIgnoringInteractionEvents