装饰模式整合UIWebView与WKWebView

1、在阅读过无数关于WebView的文章后,才有此文的出现。某种意义上,此文的初衷并非技术分享,而是对抄袭的不满。希望阅读此文的你是干干净净的。
2、选择WebView作为第一篇技术文章的原因,是因为网络上众多对于第二代webview引擎的介绍不尽人意,且关于JS交互极为模糊,做事不该是做完整吗?倘若你想琢磨,可在源码中一窥究竟。
3、如果你有更加高明的思路,请Email:xorshine@icloud.com,或者在github上说明。
4、GSWebView下载地址 GSWebView文档

  • iOS8之前闭源的UIWebView与之后开源的WKWebView,在开发中为了支持iOS8以下的系统,不免要费些功夫。很少见到一个框架能如GSWebView一般将两者的用法简化。

  • GSWebView内部是对UIWebView与WKWebView的封装,但是,它被设计成具有良好的代码体验。没有过多的类让人耳目眩晕。倘若你使用过UIWebView,那么,使用GSWebView则更加容易,你能很清楚的看出GSWebView是基本符合UIWebView的使用习惯。

  • 使用GSWebView能从根本上解决开发者对于两代web引擎封装的困惑。

1.为何要从UIWebView更新到WKWebView?

倘若你仔细观察过UIWebView的内存占用和内存泄漏,你会认为苹果的工程师在此处开了小差,而这个小差很难被接受。当你对比WKWebView时,你会感觉到它对于内存占用优化上的做出的努力。

性能测试:
UIWebViewWKWebView备注
iOS 版本8.48.4———
iPhone66真机测试
测试网页天猫首页天猫首页———
内存占用峰值132.2MB8.4MB———
加载耗时3.1s2.6smach_absolute_time();
FPS无明显差异无明显差异Instruments (core animation)
测试次数22———

注:该项测试或许存在很大的主观性,当我加载天猫首页时,这个结果出乎意料,差别大到令人难以接受。

2.如UIWebView一样使用GSWebView

  • 无数的类堆积的时候,到底是OOP还是POP,当你看到WKWebView时,GSWebView才会成为你的真爱,WKWebView的设计……哎,但性能好才是真的好!

  • 引入WebKit与JavaScriptCore库,就可开始使用GSWebView。

使用介绍:同样都是WebView,同样的款式,GSWebView如何打造不一样的内涵与代码体验?

熟悉的属性、方法

@property (nonatomic, readonly, strong) UIScrollView *scrollView;
@property (nonatomic, readonly) BOOL canGoBack;
@property (nonatomic, readonly) BOOL canGoForward; 

- (void)reload;
- (void)stopLoading;
- (void)goBack;
- (void)goForward;
//......and so on

形神皆似的协议方法

#prama mark - GSWebViewDelegate
- (BOOL)gswebView:(GSWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(GSWebViewNavigationType)navigationType;
- (void)gswebViewDidStartLoad:(GSWebView *)webView;
- (void)gswebViewDidFinishLoad:(GSWebView *)webView;
- (void)gswebView:(GSWebView *)webView didFailLoadWithError:(NSError *)error;  

3.GSWebView的JavaScript交互

  • GSWebView定义了两套协议GSWebViewDelegate和GSWebViewJavaScript,GSWebViewDelegate定义了加载状态,GSWebViewJavaScript则只定义了JS交互。

  • 当你把方法名就这么一传,连参数都不要,回调自然完成,丝滑般自然……

#prama mark - GSWebViewJavaScript
 /**
   交互协议
 */
@protocol GSWebViewJavaScript <NSObject>
@optional

/**
   调用OC方法
     
     - (NSArray<NSString *>*)gswebViewRegisterObjCMethodNameForJavaScriptInteraction
     {
        return @[@"getCurrentUserId"];
     }
 
     - (void)getCurrentUserId:(NSString *)Id
     {
        NSLong@(@"JS调用到OC%@",Id);
     }
 */
- (NSArray<NSString *>*)gswebViewRegisterObjCMethodNameForJavaScriptInteraction;
  • 改动并非是为了增加复杂度,而是GSWebView内部的WKWebView必须通过Apple.Inc指定的方法

Adding a scriptMessageHandler adds a function window.webkit.messageHandlers.<name>.postMessage(<messageBody>) for all frames.

EXAMPLE:
JS调用客户端getConsultationInfo:方法,客户端获取到id实现该方法,苹果要求必须这样做:

//获取客户端iOS版本
var version = (navigator.appVersion).match(/OS (\\d+)_(\\d+)_?(\\d+)?/);  
version = parseInt(ver[1], 10);  

if(version >= 7.0 && version < 8.0){
    getConsultationInfo(id);
}else if(version>=8.0){
    window.webkit.messageHandlers.getConsultationInfo.postMessage(id)
} 

这不是贫僧的错,要怪就怪……

4.注意事项

如果之前使用了UIWebView,如今使用GSWebView,在服务端对JS源码做出改动后,必须要考虑客户端老版本的兼容情况。当改动服务端的JS代码,势必导致老版本中的UIWebView交互失效。在下有个建议:
当GSWebView加载成功,我们调用服务端预先写好的方法 function shouldUseLatestWebView(isBool);

NSString * shouldUseLatestWebView;
if (IS_IOS_8) {
    shouldUseLatestWebView = [NSString stringWithFormat:@"shouldUseLatestWebView('%@')", @"1"];
}else{
    shouldUseLatestWebView = [NSString stringWithFormat:@"shouldUseLatestWebView('%@')", @"0"];
} 
[self.webview excuteJavaScript:jsGetCurrentUserId completionHandler:^(id  _Nonnull params, NSError * _Nonnull error) {
     if (error) {
        NSLog(@"注入JS方法shouldUseLatestWebView出错:%@",[error localizedDescription]);
    }
}];

服务端用一个全局变量保存isBool的值,当isBool为字符串1时,说明需要使用的是第二代WebView,服务端必须使用最新的交互方式代码,如果为字符串0或者空,则依旧使用原来的代码交互:

//一个全局的变量
var isBool = "";

function shouldUseLatestWebView(isBool){ 
    isBool = isBool;
}

if(isBool == "0" || isBool == ""){ 
    getConsultationInfo(id); 
}else if(isBool == "1"){ 
     window.webkit.messageHandlers.getConsultationInfo.postMessage(id);
} 

如此一来,就可以做到老版本的兼容。

5.不要吝惜你的建议

大胆的批评GSWebView!
毕竟,代码体验与用户体验,都同样,重要。

《装饰模式整合UIWebView与WKWebView》
本作品采用采用知识共享署名-非商业性使用-禁止演绎 3.0 中国大陆许可协议进行许可

    • *

    原文作者:coldliterature
    原文地址: https://segmentfault.com/a/1190000007238199
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞