0


IOS 23 实现通用WebView控制器(WKWebView)

在项目中我们经常会在多个界面使用到WebView,所以本文对WebView进行封装,实现一个通用的WebView控制器。

实现效果

简单的Webview

实现逻辑

使用系统提供的WKWebView控件,外界通过传递网址,或者字符串进行显示。

1)创建WebView控制器SuperWebController,继承自BaseTitleController。

  1. class SuperWebController: BaseTitleController {
  2. }

2)定义SuperWebController接收的两个参数uri和content。

  1. class SuperWebController: BaseTitleController {
  2. var uri:String?
  3. var content:String?
  4. }

3)重写initViews(),设置SuperWebController内容布局为RelativeLayout,并添加标题栏右边的关闭按钮 和 webView控件,webView控件使用懒加载创建。

  1. class SuperWebController: BaseTitleController {
  2. var uri:String?
  3. var content:String?
  4. override func initViews() {
  5. super.initViews()
  6. initRelativeLayoutSafeArea()
  7. //设置右侧按钮
  8. addRightImageButton(R.image.close()!.withTintColor())
  9. container.addSubview(webView)
  10. }
  11. /// 获取配置
  12. static func defaultConfiguration() -> WKWebViewConfiguration {
  13. let r = WKWebViewConfiguration()
  14. if #available(iOS 10.0, *) {
  15. r.mediaTypesRequiringUserActionForPlayback = .all
  16. } else if #available(iOS 9.0, *){
  17. r.requiresUserActionForMediaPlayback = false
  18. }else{
  19. r.mediaPlaybackRequiresUserAction = false
  20. }
  21. return r
  22. }
  23. lazy var webView: WKWebView = {
  24. let r = WKWebView(frame: CGRect.zero, configuration: SuperWebController.defaultConfiguration())
  25. r.tg_width.equal(.fill)
  26. r.tg_height.equal(.fill)
  27. return r
  28. }()
  29. }

4)获取外界传入的数据,并设置到webview上。

  1. class SuperWebController: BaseTitleController {
  2. static let CONTENT_WRAPPER_START = "<!DOCTYPE html><html><head><title></title><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\"><style type=\"text/css\"> body{font-family: Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Arial,sans-serif;word-wrap: break-word;word-break: normal;} h2{text-align: center;} img {max-width: 100%;} pre{word-wrap: break-word!important;overflow: auto;}</style></head><body>"
  3. static let CONTENT_WRAPPER_END = "</body></html>"
  4. static let WEBVIEW_BASE_URL = "http://ixuea.com"
  5. override func initDatum() {
  6. super.initDatum()
  7. if SuperStringUtil.isNotBlank(uri) {
  8. //显示网址内容
  9. //创建一个Request
  10. let request = URLRequest(url: URL(string: uri)!)
  11. //请求
  12. webView.load(request)
  13. } else {
  14. //显示字符串
  15. //由于服务端,返回的字符串,不是一个完整的HTML字符串
  16. //同时本地可能希望添加一些字体设置,所以要前后拼接为一个
  17. //完整的HTML字符串
  18. var buffer = String(SuperWebController.CONTENT_WRAPPER_START)
  19. //添加内容
  20. buffer.append(content!)
  21. buffer.append(SuperWebController.CONTENT_WRAPPER_END)
  22. //加载字符串
  23. webView.loadHTMLString(buffer, baseURL: URL(string: SuperWebController.WEBVIEW_BASE_URL))
  24. }
  25. }
  26. }

5)拦截返回按钮事件和添加关闭页面事件

  1. class SuperWebController: BaseTitleController {
  2. /// 拦截点击返回按钮
  3. override func leftClick(_ sender: QMUIButton) {
  4. if webView.canGoBack {
  5. //如果浏览器能返回上一页,就直接返回上一页
  6. webView.goBack()
  7. return
  8. }
  9. super.leftClick(sender)
  10. }
  11. override func rightClick(_ sender: QMUIButton) {
  12. finish()
  13. }
  14. /// 关闭界面
  15. func finish() {
  16. navigationController?.popViewController(animated: true)
  17. }
  18. }

6)扩展一个start方法,提供给外界启动webview。

  1. extension SuperWebController{
  2. /// 启动方法
  3. static func start(_ controller:UINavigationController,title:String?=nil,uri:String?=nil,content:String?=nil) {
  4. let target = SuperWebController()
  5. target.title = title
  6. target.uri=uri
  7. target.content = content
  8. controller.pushViewController(target, animated: true)
  9. }
  10. }

7)使用webview

  1. SuperWebController.start(navigationController!,title: data.title,uri: data.uri)

至此,简单的webview就实现了,下面继续封装 动态网页标题和进度功能。

动态标题和进度Webview

实现逻辑

如果外界没有传递标题,就显示网页标题;仿微信内部的浏览器顶部的进度条,这里要实现类似功能。进度条控件使用UIProgressView,然后监听webView进度,并设置到进度条。

1)给SuperWebController添加UIProgressView,UIProgressView控件使用懒加载创建。

  1. class SuperWebController : BaseTitleController{
  2. override func initViews() {
  3. super.initViews()
  4. initRelativeLayoutSafeArea()
  5. //设置右侧按钮
  6. addRightImageButton(R.image.close()!.withTintColor())
  7. container.addSubview(webView)
  8. container.addSubview(progressView)
  9. }
  10. lazy var progressView: UIProgressView = {
  11. let r = UIProgressView()
  12. r.tg_width.equal(.fill)
  13. r.tg_height.equal(1)
  14. //设置进度条的颜色
  15. r.progressTintColor = .colorPrimary
  16. return r
  17. }()
  18. }

2)添加标题和进度监听

  1. class SuperWebController : BaseTitleController{
  2. override func initListeners() {
  3. super.initListeners()
  4. if SuperStringUtil.isBlank(title){
  5. //监听网页标题
  6. webView.addObserver(self, forKeyPath: "title", options: .new,context: nil)
  7. }
  8. //监听加载进度
  9. webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
  10. }
  11. }

3)重写KVO监听回调,动态更新标题和进度条。

  1. class SuperWebController : BaseTitleController{
  2. /// KVO监听回调
  3. override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
  4. if let _ = object as? WKWebView{
  5. if keyPath == "title"{
  6. //标题
  7. title = webView.title
  8. }else if keyPath == "estimatedProgress"{
  9. //进度
  10. //0~1
  11. let progress = change?[.newKey] as? Float ?? 0
  12. progressView.progress = progress
  13. if progress < 1 {
  14. progressView.show()
  15. //完全不透明
  16. progressView.alpha = 1
  17. }else{
  18. UIView.animate(withDuration: 0.35, delay: 0.15) {
  19. self.progressView.alpha = 0
  20. } completion: { finished in
  21. if finished {
  22. self.progressView.hide()
  23. self.progressView.progress=0
  24. self.progressView.alpha = 1
  25. }
  26. }
  27. }
  28. }
  29. }
  30. }
  31. }

至此,动态网页标题和进度功能的webview就实现了。

标签: ios WKWebView

本文转载自: https://blog.csdn.net/sziitjin/article/details/141897910
版权归原作者 sziitjin 所有, 如有侵权,请联系我们删除。

“IOS 23 实现通用WebView控制器(WKWebView)”的评论:

还没有评论