新闻详情页面,算是UI中较为复杂一种,因为其中不乏会包括以下的功能:

1、HTML的内容展示
2、夜间模式切换
3、字体大小变更
4、评论回复功能
5、评论列表的更新

image

在iOS中关于新闻详情这类需求的解决方案有很多:

1、native

开发上难度比较大,而且也需要后台来配合样式协议的制定,优点是原生的东西,在体验以及各个方面都会很好,缺点也同样的,原生的这种做法开发成本很大。

2、Hybrid

使用webView先显示HTML页面内容,通过与JS的通信来控制HTML页面中的DOM,优点:几乎不用太多去考虑布局的问题,使用模板的形式将要显示的数据塞进HTML模板中即可,通过OC和JS中通信来达到JS调用OC,或者OC调用JS;缺点:在H5出来这么久的今天,用户体验上依然不及原生,并且一些系统级的功能组件调用比较麻烦。

今天主要说的是Hybrid这种解决方案,在iOS8以前,iOSApp中使用的是UIWebView来加载web页面,iOS8以后,Apple推出了新的框架WebKit,其中将 UIWebViewDelegate 与 UIWebView 重构成了 14 个类和 3 个协议,引入了不少新的功能和接口。

WKWebView 有以下几大主要进步:

1、将浏览器内核渲染进程提取出 App,由系统进行统一管理,这减少了相当一部分的性能损失。
2、js 可以直接使用已经事先注入 js runtime 的 js 接口给 Native 层传值,不必再通过苦逼的 iframe 制造页面刷新再解析自定义协议的奇怪方式。
3、支持高达 60 fps 的滚动刷新率,内置了手势探测。

以上特性摘自别人的话,说白了就是使用WKWebView比UIWebView性能和内存占用上都会好很多,如果要进行Hybrid开发,在iOS8之后,强烈推荐使用
WKWebView,因为同样的内容,在使用UIWebView时比WKWebView要慢很多,这在体验上是很致命的。

使用

WKWebViewJavascriptBridge GitHub地址

Objective-C
引用库
#import <WebKit/WebKit.h>
#import "WKWebViewJavascriptBridge.h"
初始化
WKWebView* webView = [[WKWebView alloc] init];
webView.navigationDelegate = self;
webView.UIDelegate = self;
[self.view addSubview:webView];
self.webView = webView;
//打开WKWebViewJavascriptBridge 的log
[WKWebViewJavascriptBridge enableLogging];
self.bridge = [WKWebViewJavascriptBridge bridgeForWebView:webView];
//设置代理
[self.bridge setWebViewDelegate:self];
加载本地的HTML文件
NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"Test" ofType:@"html"];
NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
NSURL *baseURL = [NSURL fileURLWithPath:htmlPath];
[webView loadHTMLString:[self replaceWithModelAppHemlString:appHtml] baseURL:baseURL];

绑定Handler

//registerHandler 【OC接收JS的消息】
[self.bridge registerHandler:@"ClickTest" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@"%@",data);
}];

//callHandler【OC向JS发生消息】
id data = @{ @"test": @"news" };
[self.bridge callHandler:@"ClickTest" data:data responseCallback:^(id response) {

}];
JavaScirpt

初始化

// WebViewJavascriptBridge 初始化
function setupWebViewJavascriptBridge(callback) {
    if (window.WebViewJavascriptBridge) {
        return callback(WebViewJavascriptBridge);
    }
    if (window.WVJBCallbacks) {
        return window.WVJBCallbacks.push(callback);
    }
    window.WVJBCallbacks = [callback];
    var WVJBIframe = document.createElement('iframe');
    WVJBIframe.style.display = 'none';
    WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
    document.documentElement.appendChild(WVJBIframe);
    setTimeout(function() {
        document.documentElement.removeChild(WVJBIframe)
    }, 0)
}

//WebViewJavascriptBridge 绑定事件
setupWebViewJavascriptBridge(function(bridge) {
    //registerHandler【JS接收OC的消息】
    bridge.registerHandler('ClickTest', function(data, responseCallback) {
       //改变背景颜色为黑色【Jquery操作DOM】
       $("body").css("backgroundColor","#000000"); 
    })
    //callHandler【JS向OC发送消息】
    bridge.callHandler('ClickTest', {'test': 'value'}, function responseCallback(responseData) {
    
    })
}

注意事项

1、使用WKWebView加载本地的HTML,在iOS8不能在HTML文件中引用本地的css或者js或者图片文件,只能在iOS9中这么做,iOS8需要将文件copy到temp文件夹中才行,所有不建议使用外部的css和js,可以引用远程的。

2、在iOS8中,使用一些远程的cdn的css或者js文件,必须注意在引用标签上加上charset属性,不然css和js库将会乱码

3、WKWebView性能比UIViewView性能好很多,谁用谁知道。

演示和demo查看

WKWebViewDemo Github地址

换个心情去思考问题,也许很多难题就会迎刃而解。