将UIWebView代理迁移到WKWebView代理方法

26

我正在将UIWebView迁移到WKWebView。我已更改了所有Delegate方法。我需要WKWebView的Delegate方法等于下面UIWebView的Delegate方法。应用程序工作得很好。但是登录会话没有保留

UIWebView:

    extension WebViewController: UIWebViewDelegate {

    func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {

    guard let url = request.url else {
       return true
    }

    guard !url.absoluteString.contains("data:application/pdf") else {
        navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.action,
                                                            target: self,
                                                            action: #selector(share(sender:)))
        return true
    }

    guard url.pathExtension != "pdf" else {
        let safariVC = SFSafariViewController(url: url)
        safariVC.modalPresentationStyle = .popover
        present(safariVC, animated: true, completion: nil)
        return false
    }

    guard url.isLogin() == false else {
        AppDelegate.navigationController.signOut(.sessionOnly)
        return false
    }

    guard let mobileSite = url.asMobileSite() else {
        return true
    }

    let mobileRedirect = URLRequest(url: mobileSite)
    webView.loadRequest(mobileRedirect)
    return false

}

func webViewDidStartLoad(_ webView: UIWebView) {
    numberOfDidStartLoads += 1
}

func webViewDidFinishLoad(_ webView: UIWebView) {
    numberOfDidStartLoads -= 1
}

func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
    numberOfDidStartLoads -= 1
}
}

我尝试了下面的代码,但会出现会话过期的问题。

Translated text:

我尝试了下面的代码,但会出现会话过期的问题。

extension WebViewController: UIWebViewDelegate {

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (_: WKNavigationActionPolicy) -> Void) {

    guard let url = navigationAction.request.url else {
        decisionHandler(.allow)
        return
    }

    guard !url.absoluteString.contains("data:application/pdf") else {
        navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.action,
                                                            target: self,
                                                            action: #selector(share(sender:)))
        decisionHandler(.allow)
        return
    }

    guard url.pathExtension != "pdf" else {
        let safariVC = SFSafariViewController(url: url)
        safariVC.modalPresentationStyle = .popover
        present(safariVC, animated: true, completion: nil)
        decisionHandler(.cancel)
        return
    }

    guard url.isLogin() == false else {
        AppDelegate.navigationController.signOut(.sessionOnly)
        decisionHandler(.cancel)
        return
    }

    guard let mobileSite = url.asMobileSite() else {
        decisionHandler(.allow)
        return
    }

    let mobileRedirect = URLRequest(url: mobileSite)
    webView.load(mobileRedirect)
    decisionHandler(.cancel)
    return

    decisionHandler(.allow)

}

    func webViewDidStartLoad(_ webView: UIWebView) {
        numberOfDidStartLoads += 1
    }

    func webViewDidFinishLoad(_ webView: UIWebView) {
        numberOfDidStartLoads -= 1
    }

    func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
        numberOfDidStartLoads -= 1
    }
}
请帮我解决这个问题。我在将代码从UIWebView更改为WKWebView时犯了一些错误。

可能是Migrating from UIWebView to WKWebView的重复问题。 - Tamás Sengel
你能提供有关崩溃的更多信息吗?在这个方法中,你必须调用 decisionHandler,崩溃是否可能与此有关? - Mert Buran
在调试时,您是否有异常断点?AppDelegate不应该在这里崩溃。 - Mert Buran
@MertBuran 有什么想法吗? - Siva
@shallowThought 问题在于会话没有保留。 - Siva
显示剩余5条评论
4个回答

8

在您的代码中,可能需要实现以下操作,这意味着不要使用 UIWebViewDelegate 协议,而是尝试使用 WKNavigationDelegate 协议。我猜想在处理会话时,您可能会错过其中一个最重要的函数。

   func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        print(#function)
        completionHandler(.performDefaultHandling,nil)
    }

有不同类型的AuthChallengeDisposition,例如

public enum AuthChallengeDisposition : Int {


    case useCredential

    case performDefaultHandling

    case cancelAuthenticationChallenge

    case rejectProtectionSpace
}

WKNavigationDelegate协议的完整内容如下:

  extension ViewController: WKNavigationDelegate{
    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        print(#function)
        completionHandler(.performDefaultHandling,nil)
    }

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        print(#function)
        decisionHandler(.allow)
    }

    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        print(#function)
        decisionHandler(.allow)
    }
}

我猜测会话没有保留。在UIWebView中,同样的事情运作良好。你需要更多的信息吗? - Siva
@Siva,你有关于会话不保留的任何解决方案吗? - Bhargav B. Bajani

2
我猜你可以使用 webView(_:decidePolicyFor:decisionHandler:) 方法,来阻止/取消或允许请求。这样应该可以达到相同的效果。 免责声明:我还没有测试过,一旦有时间我会尽快测试。

1
分析你的代码,我发现由于之前的“return”语句,某个语句永远不会被执行。
该语句为:
decisionHandler(.allow)

您可以在函数的最后一行找到它的代码:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (_: WKNavigationActionPolicy) -> Void)

你放弃了这个方法:
func webViewDidStartLoad(_ webView: UIWebView) {
    numberOfDidStartLoads += 1
}

-2

UIWebView在新的应用程序发布中已经过时,您可以使用UIWebview,但是应用程序可能会被拒绝,请检查并更新到WKWebView。

----------------- UIWebViewDelegate 代理方法 -------------

func webViewDidStartLoad(_ webView: UIWebView) { }

func webViewDidFinishLoad(_ webView: UIWebView) { }

func webView(_ webView: UIWebView, didFailLoadWithError error: Error) { }

--------------- 替换为 WKNavigationDelegate 代理方法--------------

func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {}

func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接