iOS12 bug总结(持续更新)

iOS12fix掉的问题:

第一、iOS11.3 WKWebView的多选图片功能出现了bug。我们apple的架构设计如下:

rootViewController为UITabBarController,然后add了五个NavigationController,这里的bug主要的表现是:当用户在wkwebview中唤起相册后选取多张相片,相册的右上角一直都是取消按钮,没有完成按钮,导致无法选取图片。

iOS12.0版本该问题消失。

iOS12出现的问题:

第一、webview内打开全屏播放器播放完视频后,状态栏被隐藏

iOS12 bug总结(持续更新)_第1张图片iOS12 bug总结(持续更新)_第2张图片iOS12 bug总结(持续更新)_第3张图片

 

如上图,图一在视频未播放时状态栏正常,图二是全屏播放h5视频,图三退出全屏时状态栏消失。

修复:

全屏视频的播放本质上是新加了一个window,且该window最终包裹了视频播放的VC,当退出全屏视频时,其实是对应的window进行了隐藏,所以,我们可以监听window隐藏的通知:

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(windowDidBecomeHidden:) name:UIWindowDidBecomeHiddenNotification object:nil];

在该通知触发时去把状态栏设置回来。

 

这种修改需要考虑以下几种情况:

1、当前应用可能同时存在多个webview,而且应用本身的某些页面存在确切的隐藏状态栏的需求,所以,不能简单的监听到通知后就把状态栏显示。因此:

第一、不能把这个逻辑放在webview这一层;

第二、这个逻辑可以放在webviewVC这一层,但是需要保证webviewVC正在展示才行;

第三、iOS12以上的条件;

第四、当前window确实时播放视频所加的window,其他window的变化不能触发该逻辑;

前三点很容易做到,第四点,我们的实现是这样的:


        UIWindow * win = (UIWindow *)noti.object;
        if(win){
            UIViewController *rootVC = win.rootViewController;
            NSArray<__kindof UIViewController *> *vcs = rootVC.childViewControllers;
            if([vcs.firstObject isKindOfClass:NSClassFromString(@"AVPlayerViewController")]){
                [[UIApplication sharedApplication]setStatusBarHidden:false animated:false];
            }
        }

这样就可以保证在确定的window隐藏时才触发设置状态栏的操作。

第二、kscrash记录僵尸对象时,NSException的对象会引起crash!


0	xxxx	getClassRW (in xxxx) (KSObjC.c:239)
1	xxxx	getClassRO (in xxxx) (KSObjC.c:245)
2	xxxx	ksobjc_ivarValue (in xxxx) (KSObjC.c:811)
3	xxxx	copyStringIvar (in xxxx) (KSZombie.c:73)
4	xxxx	storeException (in xxxx) (KSZombie.c:107)
5	xxxx	handleDealloc (in xxxx) (KSZombie.c:125)
6	xxxx	handleDealloc_NSObject (in xxxx) (KSZombie.c:149)
7	CoreFoundation	-[NSException dealloc] (in CoreFoundation) + 136

这里NSException在dealloc时ks去记录僵尸信息时会崩溃。其原因如下:

https://github.com/kstenerud/KSCrash/issues/292

主要是苹果修改了一个mask(ISA_MASK)的值引起了崩溃。

这里需要再次强调一下,NSException对象一般是try-catch机制的产物,我曾经在一篇文章中提到过:

https://blog.csdn.net/u012413955/article/details/79816579

try-catch会引起内存泄露。大家在用OC编码时还是要遵守苹果的开发规范,尽量不要使用try-catch来处理异常。

第三、UIWebView键盘弹起会遮挡输入框!

这个问题是有业务被降级到了UIWebView后,发现iOS12.x上存在此问题,相应的wkwebview就没有这样的问题,考虑到苹果不再维护UIWebView,所以,我们不打算再去解决UIWebView上的问题,尽量解决wkwebview的业务问题,然后切换到wkwebview才是正道。

第四、WKWebView的输入键盘隐藏时页面不会回归到原来的位置!

https://github.com/apache/cordova-ios/issues/417

该bug的具体描述如上述issue。主要的场景为:Xcode10打包时iOS12以上的系统会出现问题。影响:点击页面其他区域可以让页面回滚,所以是个体验问题。

目前该issue下提到的h5层面和原生层面的解决方案都有问题,这里列举两个:

/**
 * observer notification when keyboard will hide
 */
[[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillHide)
                                                     name:UIKeyboardWillHideNotification
                                                   object:nil];

/////////////--------------------------//////////////
/*
 *Description: this method was trigger by selector keyboarwillhide from notification
 */
-(void)keyboardWillHide
{
    if (@available(iOS 12.0, *)) {
        WKWebView *webview = (WKWebView*)self.webView;
         for(UIView* v in webview.subviews){
              if([v isKindOfClass:NSClassFromString(@"WKScrollView")]){
                      UIScrollView *scrollView = (UIScrollView*)v;
                      [scrollView setContentOffset:CGPointMake(0, 0)];
              }
          }
     }
}

这是原生层面的解决方案,我实测也确实可以,不过有两个问题:

第一、WKScrollView是私有类,不能直接使用,否则违反苹果的审核规则;这里我测试了wkwebview的scrollview来代替这里的wkscrollview,但是不生效。重新审视一下wkwebview的scrollview的属性:

#if TARGET_OS_IPHONE
/*! @abstract The scroll view associated with the web view.
 */
@property (nonatomic, readonly, strong) UIScrollView *scrollView;
#endif

这里有个注释需要注意一下:“abstract”,所以,可以大胆猜测这里的scrollview是wkscrollview的代理,并非实际的view。

第二、 [scrollView setContentOffset:CGPointMake(0, 0)];是将页面回滚到top,这个显然是不对的。

这里我试验了一下,可以再注册一个通知UIKeyboardWillShowNotification,此通知触发时cache当前的contentOffset,然后在UIKeyboardWillHideNotification的时机将cachedContentOffset设置为scrollView的contentOffset。此方案我验证过,暂时没有发现问题,如果有人愿意采用一些小技巧而使用wkscrollview,可以参考此方案。

下面有个js层面的解决方案

window.addEventListener('keyboardDidHide', function() {
    if (window.pageYOffset != 0) {
      window.scrollTo(0, 0);
    }
});

有同事试过后,发现有兼容性问题,iPhone X不生效。

所以,目前看这个问题最终还是需要apple在后续的版本中修复了。

你可能感兴趣的:(WebView,iOS12,系统状态栏隐藏,NSException,KSCrash)