返回

iOS状态栏难题:揭开iOS 13及更高版本之谜

IOS

进入视频播放页面后,在iOS 13及更高版本中,对状态栏进行修改的操作突然失灵。最初,我们百思不得其解,但深入探究后,发现幕后黑手竟是iOS 13中引入的Scene适配和一个鲜为人知的UIWindow。

Scene与状态栏

iOS 13中引入的Scene概念彻底改变了应用程序与状态栏的交互方式。Scene是独立的界面区域,每个Scene都有自己独立的状态栏。这意味着应用程序现在可以对每个Scene的状态栏进行独立控制。

然而,这带来了一个挑战:当应用程序进入视频播放页面时,iOS 13会自动创建一个新的Scene,并将其置于所有其他Scene之上。这个新的Scene拥有自己的状态栏,并且不受应用程序对其他Scene状态栏所做的更改的影响。

隐藏的UIWindow

另一个导致状态栏问题的原因是一个隐藏的UIWindow。UIWindow是应用程序窗口的容器,它通常用于显示应用程序的主界面。在iOS 13中,视频播放器使用了称为AVPlayerViewController的新控件,它会在视频播放期间创建一个隐藏的UIWindow。

这个隐藏的UIWindow同样拥有自己的状态栏,并且优先级高于应用程序其他Scene的状态栏。因此,即使应用程序尝试更改其状态栏,隐藏的UIWindow仍会将其覆盖。

解决方案

为了解决这个问题,我们采取以下措施:

  1. 重写viewWillAppear方法 :我们在viewWillAppear方法中,检查当前Scene是否处于视频播放状态。如果是,我们使用[sharedApplicationWindow]获取隐藏的UIWindow,然后对其状态栏进行必要的更改。
- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];

  if ([self isVideoPlayingScene]) {
    UIWindow *sharedApplicationWindow = [[UIApplication sharedApplication] keyWindow];
    [self updateStatusBarForWindow:sharedApplicationWindow];
  }
}
  1. 更新状态栏 :在updateStatusBarForWindow方法中,我们对隐藏的UIWindow的状态栏进行必要的更改。
- (void)updateStatusBarForWindow:(UIWindow *)window {
  window.windowLevel = UIWindowLevelStatusBar + 1;
  [self setStatusBarStyle:UIStatusBarStyleLightContent];
  [self setStatusBarHidden:NO];
}
  1. 针对不同场景设置状态栏样式 :我们在viewWillAppear方法中添加判断逻辑,针对不同的场景设置不同的状态栏样式。
- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];

  if ([self isVideoPlayingScene]) {
    [self updateStatusBarForVideoPlayingScene];
  } else {
    [self updateStatusBarForDefaultScene];
  }
}

总结

通过识别iOS 13中Scene和隐藏UIWindow对状态栏行为的影响,我们能够成功解决状态栏问题。通过遵循以上解决方案,应用程序可以在iOS 13及更高版本中正常控制其状态栏。

这个案例研究突出了在移动开发中持续学习和适应的重要性。随着新技术的出现,开发人员必须不断调整他们的方法,以确保应用程序提供最佳的用户体验。