浮生猎趣

ls *.fun

App适配iOS8遇到的兼容问题:键盘方向与StatusBar方向不一致,阻止锁屏失效,OpenGL崩溃

| Comments

ios8 adapt 苹果正式发布iOS8系统,到现在安装覆盖率已达48%,而iOS7的安装率是49%。所以,各位开发者又有得忙了,把所有的App都升级并适配到iOS8系统可不是一件轻松的事。

下面罗列一下我在适配iOS8过程中遇到的兼容问题——而同样的代码在iOS6/7是完全没问题的。

1. 键盘弹出方向与StatusBar方向不一致

在App中,第一个ViewController是只支持竖屏方向(Portrait)的,切换到第二个页面,默认也是Portrait,但用户可以点击按钮切换为横屏(Landscape)。

所以,我把App-Info.plist只选中了Portrait一项,并且在Root ViewController重载了以下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (BOOL)shouldAutorotate
{
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

然后在需要切换到横屏的时候,调用以下代码:

1
2
3
4
5
- (void)onFullScreenButtonTouchUpInside:(id)sender
{
    [self adjustViewFrameToFullScreen];
    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
}

由于在iOS6、7中,键盘方向是跟随状态栏方向的,所以一切表现正常,横屏下,无论设备方向怎样,键盘都是横着弹出。

但是,在iOS8中,键盘却随着设备方向弹出了。换言之,即使Interface Orientation为Landscape,但Device Orientation为Portrait,键盘就会以Portrait的方向弹出
如下图:

ios8 adapt keyboard

1.1 解决方法

我想要的是键盘不管设备方向,只关注状态栏方向,也就是StatusBarOrientation。由于iOS8新出不久,在网上没找到解决方案。后来我一同事发现手动更改设备方向可以解决这一问题:

1
2
3
4
5
6
7
8
9
- (void)onFullScreenButtonTouchUpInside:(id)sender
{
    [self adjustViewFrameToFullScreen];
    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
    //改设备方向
    if (IsIOS8) {
        [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIDeviceOrientationLandscapeLeft] forKey:@"orientation"];
    }
}

2. 禁用屏幕自动锁定失效

本来,防止屏幕锁定只需一句代码:

1
    [[UIApplication sharedApplication] setIdleTimerDisabled:YES];

但是,在iOS8中,偶尔会失效。测试人员发现了这个问题是在弹出键盘点击发送后必现,而原因不明。因为键盘出现与隐藏,理论上不应该影响这个idleTimerDisabled的属性。暂且认为是iOS8的Bug吧。

2.1 解决方法

在键盘收起的时候,重设IdleTimerDisabled

1
2
3
4
5
6
    - (void)onKeyboardDidHide:(NSNotification *)notification
  {
      if (IsIOS8) {
          [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
      }
  }

3. OpenGL ES渲染时崩溃

在iOS中使用OpenGL ES渲染,切换到后台时需要停止渲染,否则会引起崩溃。见这里:How to fix OpenGL ES application crashes when moving to the background

但是在iOS8中,即使不是切换到后台,而是通过NavigationController切换到另一个ViewController再切回来,也会引起崩溃,崩溃点在:

1
    [EAGLContext presentRenderbuffer:GL_RENDERBUFFER];

猜测可能是,在iOS 8中,如果OpenGL的视图如果切换到不可见的ViewController,也需要停止绘制,否则也会引起在后台渲染OpenGL类似的崩溃。

3.1 解决方法

在ViewWillDisapper的时候停止渲染。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    - (void)viewWillDisappear:(BOOL)animated
  {
      [super viewWillDisappear:animated];
  
      if (_videoView && IsIOS8) {
          [_videoView pauseVideo];
      }
  }
  
  - (void)viewWillAppear:(BOOL)animated
  {
      [super viewWillAppear:animated];
  
      if (_videoView && IsIOS8) {
          [_videoView resumeVideo];
      }
  }

iOS的兼容真是个蛋疼的问题。

原文作者: lslin
原文链接: http://blog.lessfun.com/blog/2014/09/24/ios8-issue-keyboard-orientation-and-idletimerdisabled-not-working/
版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0

发表评论