WKWebView的基础知识

WKWebView是iOS8以后推出的WebKit框架,是为了解决UIWebView加载速度慢、内存占用大的问题,还解决了加载网页时的内存泄漏问题。

一、WKWebView框架

WKWebView框架

二、WKWebViewAPI属性方法

使用 init(frame: CGRect, configuration: WKWebViewConfiguration) 方法创建了一个新的WKWebView对象之后,你需要加载web内容。使用 loadHTMLString("",baseURL:url) 方法加载本地 HTML 文件或者使用 load(request) 方法开始加载 web 内容。使用 stopLoading() 方法停止加载,并且使用 isLoading 属性查看 web 视图是否正在加载中。为对象设置委托属性以遵守WKUIDelegate协议,以跟踪Web内容的加载。

要允许用户在 web 历史页面中前进或者后退,为按钮设置使用 goBack()goForward()方法的动作。当用户不能在某个方向上再移动时,使用canGoBackcanGoForward属性禁用按钮。

1. 初始化视图

// 初始化视图配置信息
/// 配置状态
    public lazy var wkWebConfig: WKWebViewConfiguration = {
        let config = WKWebViewConfiguration()
        config.userContentController = userContentController
        addtargetFunctionName()
        config.preferences.javaScriptEnabled = true
        config.preferences.javaScriptCanOpenWindowsAutomatically = true
        return config
    }()

// 指定frame和configuration初始化web视图
let tmpView = WKWebView.init(frame: .zero, configuration: wkWebConfig)

2. 设置委托

// 导航代理
tmpView.navigationDelegate = self
// UI代理
tmpView.uiDelegate = self

3. web信息

// 与web视图相关联的滚动视图
open var scrollView: UIScrollView { get }

// 页面标题,一般使用KVO动态获取
open var title: String? { get }

// 页面URL
open var url: URL? { get }

// 自定义用户代理字符串,会覆盖默认的值,iOS9之后有效
open var customUserAgent: String?

// 用于当前导航的SecTrustRef对象,iOS10之后有效
open var serverTrust: SecTrust? { get }

4. 加载视图内容

  • 加载请求web视图
// 导航到请求的URL地址
open func load(_ request: URLRequest) -> WKNavigation?

// 找到文件系统上所请求的文件URL
open func loadFileURL(_ URL: URL, allowingReadAccessTo readAccessURL: URL) -> WKNavigation?

// 设置网页内容和baseURL
open func loadHTMLString(_ string: String, baseURL: URL?) -> WKNavigation?

// 设置网页内容和baseURL
open func load(_ data: Data, mimeType MIMEType: String, characterEncodingName: String, baseURL: URL) -> WKNavigation?
  • 页面加载
// 页面加载进度,一般使用KVO动态获取
open var estimatedProgress: Double { get }

// 指示页面上的所有资源是否通过安全加密的连接加载
open var hasOnlySecureContent: Bool { get }

// 页面是否加载中
open var isLoading: Bool { get }

// 重新加载当前页面
open func reload() -> WKNavigation?

// 重新加载当前页面,如果可能,使用缓存验证条件执行端到端重新验证
open func reloadFromOrigin() -> WKNavigation?

// 停止加载当前页面所有资源
open func stopLoading()

5. 导航

// 可返回的页面列表
open var backForwardList: WKBackForwardList { get }

// 是否可返回
open var canGoBack: Bool { get }

// 是否可向前
open var canGoForward: Bool { get }

// 是否允许手势左滑返回上一级,类似导航控制的左滑返回
open var allowsBackForwardNavigationGestures: Bool

// 用于确定是否按下链接可以显示链接目标的预览
open var allowsLinkPreview: Bool

// 返回上一级
open func goBack() -> WKNavigation?

// 前进下一级, 需要曾经打开过, 才能前进
open func goForward() -> WKNavigation?

// 返回到列表中的指定项
open func go(to item: WKBackForwardListItem) -> WKNavigation?

6. 缩放内容

注意:需要非iPhone(!TARGET_OS_IPHONE)

// 放大手势是否会改变网页视图的放大倍数 
@property (nonatomic) BOOL allowsMagnification;

// 页面内容当前缩放因子
@property (nonatomic) CGFloat magnification;

// 按指定的因子缩放页面内容,并将结果居中在指定的点上
- (void)setMagnification:(CGFloat)magnification centeredAtPoint:(CGPoint)point

7. 执行JavaScript(OC调用JavaScript方法)

open func evaluateJavaScript(_ javaScriptString: String, completionHandler: ((Any?, Error?) -> Void)? = nil)

三、WKWebViewConfiguration

使用 WKWebViewConfiguration 类,你可以确定网页呈现的速度,媒体播放的处理方式,用户可以选择的项目的粒度等等。
WKWebViewConfiguration 仅在首次初始化Web视图时使用。 当web视图被创建以后,你就无法再使用此类来更改Web视图的配置信息了。

1. 配置webview状态

// 用户交互类
open var userContentController: WKUserContentController

// 视图要使用的首选项设置。
open var preferences: WKPreferences

2. 视图首选项配置

webView.perferences 配置

// 是否允许内容的javaScript
config.preferences.javaScriptEnabled = true
// JavaScript是否可以在没有用户交互的情况下打开窗口
config.preferences.javaScriptCanOpenWindowsAutomatically = true

四、WKUserContentController用户交互

使用 WKWebViewConfiguration 类,可以添加用户交互的方法,JavaScript调用原生

1. 添加回调代理类

import WebKit

class WKScriptMessageDelegate: NSObject, WKScriptMessageHandler {
    public weak var scriptDelegate: WKScriptMessageHandler?
    
    init(_ delegate: WKScriptMessageHandler) {
        super.init()
        scriptDelegate = delegate
    }
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        scriptDelegate?.userContentController(userContentController, didReceive: message)
    }
}

2. 初始化用户交互实例

public lazy var userContentController: WKUserContentController = {
        let userContent = WKUserContentController()
        return userContent
    }()
config.userContentController = userContentController

3. 添加调用交互方法

public func addTarget(_ target: WKScriptMessageHandler, functionName: String) {
        userContentController.add(WKScriptMessageDelegate(target), name: functionName)
    }

4. 遵循代理协议

extension BaseWebViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        let funcName = message.name
        let params = "\(message.body)"
        print(funcName + "---" + "\(params)")
        // 调用方法的名称
        switch funcName {
        case "openBrowser":
            openBrowser(params)
        default:
            break
        }
//        webView.evaluateJavaScript("getUserInfoSuccess(true)")
    }
}

五、网页导航代理

    /**
     根据webView、navigationAction相关信息决定这次跳转是否可以继续进行,这些信息包含HTTP发送请求,如头部包含User-Agent,Accept,refer
     在发送请求之前,决定是否跳转
     */
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        // ...(实现url重定向)
        let urlStr = navigationAction.request.url?.absoluteString
        print(urlStr ?? "发送请求之前 url为空")
        decisionHandler(.allow)
    }
    /** 身份验证 */
    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
//            let card = URLCredential.init(trust: challenge.protectionSpace.serverTrust ?? <#default value#>)
            completionHandler(URLSession.AuthChallengeDisposition.useCredential, nil)// 设置为nil,不要证书验证
        } else {
            completionHandler(URLSession.AuthChallengeDisposition.performDefaultHandling, nil)// 设置为nil,不要证书验证
        }
        
    }
    /**
     * 这个代理方法表示当客户端收到服务器的响应头,根据response相关信息,可以决定这次跳转是否可以继续进行。
     * 在收到响应后,决定是否跳转
     */
    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        decisionHandler(.allow)
    }
    /** 接收到服务器跳转请求之后调用*/
    func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
        
    }
    /** 页面加载失败。*/
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        print(error.localizedDescription)
        
    }
    /** WKWebView终止 */
    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
        
    }
    // MARK: - 页面内监听
    
    /** 页面开始加载时调用 */
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        
    }
    /** 当内容开始返回时调用 */
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        
    }
    
    /** 页面加载完成之后调用 */
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        if shouldHideNavBar == false {
            self.navTitle = self.webView.title
        }
    }
    /** 页面加载失败时调用 */
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        
    }

六、UI代理

/// web界面中有弹出警告框时调用 !必须实现
    /// - Parameters:
    ///   - webView: 实现该代理的webview
    ///   - message: 警告框中的内容
    ///   - frame: 主窗口
    ///   - completionHandler: 警告框消失调用
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        let alert = UIAlertController(title: "提醒", message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "知道了", style: .cancel, handler: { _ in
            completionHandler()
        }))
        self.present(alert, animated: true)
    }
    // 输入框
    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
        completionHandler("wkwebview")
    }
    // 确认框
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
        completionHandler(true)
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值