第一、iOS11.3 WKWebView的多选图片功能出现了bug。我们apple的架构设计如下:
rootViewController为UITabBarController,然后add了五个NavigationController,这里的bug主要的表现是:当用户在wkwebview中唤起相册后选取多张相片,相册的右上角一直都是取消按钮,没有完成按钮,导致无法选取图片。
iOS12.0版本该问题消失。
如上图,图一在视频未播放时状态栏正常,图二是全屏播放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隐藏时才触发设置状态栏的操作。
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后,发现iOS12.x上存在此问题,相应的wkwebview就没有这样的问题,考虑到苹果不再维护UIWebView,所以,我们不打算再去解决UIWebView上的问题,尽量解决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在后续的版本中修复了。