【iOS开发】从 UIWebView 到 WKWebView
2016-03-20 23:44
501 查看
大家也可以关注我的微信公众号bluefish_ios查看更多更新的一些技术文章分享。
② UIWebView 和 WKWebView 的区别
WKWebView 更快(占用内存可能只有 UIWebView 的1/3~1/4),没有缓存,更为细致地拆分了 UIWebViewDelegate 中的方法。
想要了解更多关于 WKWebView 的特性的,可以自行 Google,这里你可以简单地把它当做是轻量级的 UIWebView。
③为什么现在是时候从 UIWebView 迁移到 WKWebView 了:
截止到我写这篇文章的时候,据 mixpanel 的数据,iOS 9 占有率已达 58.55%,iOS 8 占有率达到了 34.78%,iOS 7 及更早版本是 6.66%,而那 6.66% 应该大部分都是对手机使用极度不频繁的人。所以从现在开始,再开发 App 只兼容 iOS 8 和 iOS 9 两个版本就可以了(如果你的产品对覆盖率要求不是很苛刻的话)。WKWebView 是 iOS 8 之后才有的 WebKit 中的内容,所以之前我们要同时兼容 iOS 7 和 iOS 8 的时候,可以推辞说 UIWebView
和 WKWebView 一起做太麻烦了,现在可没有理由拒绝新东西了。
在 WKWebView 中,UIWebViewDelegate 与 UIWebView 被重构成了14类与3个协议,下面给出一些在 UIWebView 中常用的方法的 WKWebView 版本。
以上方法分别存在于 UIWebViewDelegate 和 WKNavigationDelegate 中。
如果你之前只是用到了以上列出的 UIWebViewDelegate 中的几个方法,那么只是简单地换一个方法名,让你的 ViewController 继承 WKNavigationDelegate ,继续用就可以了。想要更多内容可以自己用 cmd键+鼠标左击『WKNavigationDelegate』通过 Xcode 查看。
要注意的是
下面的示例代码用于从 WKWebView 中获取网页中的文本。
可能你也注意到了,把 JS 脚本注入到 WebView 的途径是初始化一个 WebView,所以你需要在 WebView 初始化之前写好自己的脚本。当然如果你不需要 JS 交互,直接用一个 frame 来初始化 WebView,去掉 configuration 参数就好了。
然而,我们如何拿到从 WKWebView 中抓取到的文本呢(通过 document.body.innerText 这一句)?
如上面所说,让你的 ViewController 在继承了 WKNavigationDelegate 之后再继承一下 WKScriptMessageHandler 。然后实现 WKNavigationDelegate 中唯一的一个方法:
乍一看这里可能会有疑惑:我们给 WKWebView 绑定了 WKNavigationDelegate,但是 WKScriptMessageHandler 并没有提供代理方法啊。其实与此相对应的过程出现在上一段代码中的第5行:
引言
①本文章适合有 UIWebView 基础的人看,如果实在没用过的话,至少你要知道 UIWebView 是个什么东西。② UIWebView 和 WKWebView 的区别
WKWebView 更快(占用内存可能只有 UIWebView 的1/3~1/4),没有缓存,更为细致地拆分了 UIWebViewDelegate 中的方法。
想要了解更多关于 WKWebView 的特性的,可以自行 Google,这里你可以简单地把它当做是轻量级的 UIWebView。
③为什么现在是时候从 UIWebView 迁移到 WKWebView 了:
截止到我写这篇文章的时候,据 mixpanel 的数据,iOS 9 占有率已达 58.55%,iOS 8 占有率达到了 34.78%,iOS 7 及更早版本是 6.66%,而那 6.66% 应该大部分都是对手机使用极度不频繁的人。所以从现在开始,再开发 App 只兼容 iOS 8 和 iOS 9 两个版本就可以了(如果你的产品对覆盖率要求不是很苛刻的话)。WKWebView 是 iOS 8 之后才有的 WebKit 中的内容,所以之前我们要同时兼容 iOS 7 和 iOS 8 的时候,可以推辞说 UIWebView
和 WKWebView 一起做太麻烦了,现在可没有理由拒绝新东西了。
正文
常用代理方法
在 WKWebView 中,UIWebViewDelegate 与 UIWebView 被重构成了14类与3个协议,下面给出一些在 UIWebView 中常用的方法的 WKWebView 版本。//准备加载页面 [code]UIWebViewDelegate - webView:shouldStartLoadWithRequest:navigationType
WKNavigationDelegate - webView:didStartProvisionalNavigation:
//已开始加载页面,可以在这一步向view中添加一个过渡动画 [code]UIWebViewDelegate - webViewDidStartLoad:
WKNavigationDelegate - webView:didCommitNavigation:
//页面已全部加载,可以在这一步把过渡动画去掉 [code]UIWebViewDelegate - webViewDidFinishLoad:
WKNavigationDelegate - webView:didFinishNavigation:
//加载页面失败 [code]UIWebViewDelegate - webView:didFailLoadWithError:
WKNavigationDelegate - webView:didFailNavigation:withError:
WKNavigationDelegate - webView:didFailProvisionalNavigation:withError:
以上方法分别存在于 UIWebViewDelegate 和 WKNavigationDelegate 中。
如果你之前只是用到了以上列出的 UIWebViewDelegate 中的几个方法,那么只是简单地换一个方法名,让你的 ViewController 继承 WKNavigationDelegate ,继续用就可以了。想要更多内容可以自己用 cmd键+鼠标左击『WKNavigationDelegate』通过 Xcode 查看。
要注意的是
webview.delegate = self需要改写为
webview.navigationDelegate = self。
JS交互
在 UIWebView 中,一句简单的webView.stringByEvaluatingJavaScriptFromString()就可以用 JS 脚本操纵 WebView,在 WKWebView 中,我们可能需要用到
WKScriptMessageHandler这个协议中的
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage)方法。
下面的示例代码用于从 WKWebView 中获取网页中的文本。
let js = "window.webkit.messageHandlers.observe.postMessage(document.body.innerText);" // 注意这里的observe字段是自己写的,不是固定的写法,参考第6行 let script = WKUserScript(source: js, injectionTime: WKUserScriptInjectionTime.AtDocumentEnd, forMainFrameOnly: true) // 这里的 AtDocumentEnd 字段是指网页中的内容加载完毕后再插入 JS 脚本,你也可以选择 AtDocumentStart,在 document element 刚刚创建时就插入脚本,看具体需求 let config = WKWebViewConfiguration() config.userContentController.addUserScript(script) config.userContentController.addScriptMessageHandler(self, name: "observe") // 对应第一行 JS 脚本中的observe字段 //初始化WKWebView let webview = WKWebView( frame: CGRectMake(0, 0, self.view.frame.width, self.view.frame.height), configuration: config) webview.navigationDelegate = self self.view.addSubview(webview) //加载网页 webview.loadRequest(NSURLRequest(URL: NSURL(string: "http://www.jianshu.com")!))
可能你也注意到了,把 JS 脚本注入到 WebView 的途径是初始化一个 WebView,所以你需要在 WebView 初始化之前写好自己的脚本。当然如果你不需要 JS 交互,直接用一个 frame 来初始化 WebView,去掉 configuration 参数就好了。
然而,我们如何拿到从 WKWebView 中抓取到的文本呢(通过 document.body.innerText 这一句)?
如上面所说,让你的 ViewController 在继承了 WKNavigationDelegate 之后再继承一下 WKScriptMessageHandler 。然后实现 WKNavigationDelegate 中唯一的一个方法:
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage){ let str:NSString = message.body as! NSString // 因为我们抓取到的是文本,这里把 message.body 强制转换为 NSString,如果你通过 JS 拿到的是其他信息,按需转换 print(str) }
乍一看这里可能会有疑惑:我们给 WKWebView 绑定了 WKNavigationDelegate,但是 WKScriptMessageHandler 并没有提供代理方法啊。其实与此相对应的过程出现在上一段代码中的第5行:
config.userContentController.addScriptMessageHandler这一句。
相关文章推荐
- Android开发初学者必看文档:Android开发规范
- android多任务下载的状态更新
- Design Patterns Apply On Soccer Engine
- iOS定位原理和使用建议(转)
- Android中设置按钮监听事件
- Android——Activity恢复用户用EditText输入的数据
- Swift语言学习笔记(3)
- Android——保存和恢复用户状态
- Android菜鸟App开发,第一个App(第一天)
- 关于APP分层简单框架思路
- QQ也可以和微信一样只能共同好友见评论
- Retrofit2的简单应用与封装
- 线程间通信 1全局变量2当前主对话框指针3发消息方式4 AfxBeginThread的返回值(为CWinThread类型的指针)5AfxGetApp
- Android进阶之线程池
- JNI的使用和注意事项
- Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant)
- Android 应用界面开发笔记 自定义控件与Handler -待更新
- Android5.x 新控件之RecyclerView使用总结
- iOS中Cookie的使用
- 一个强大的Android模拟器Genymotion