【问题标题】:How to add Activity Indicator to WKWebView (Swift 3)如何将活动指示器添加到 WKWebView (Swift 3)
【发布时间】:2017-04-10 17:17:33
【问题描述】:

我的应用中有一个 wkwebview,我想向它添加一个活动指示器。我希望它出现在 webview 加载时出现的位置,并且在完成加载时消失,它消失了。你能给我一些代码来做到这一点吗?这是我现在的代码:

@IBOutlet weak var Activity: UIActivityIndicatorView!
var webView : WKWebView!


@IBOutlet var containerView: UIView? = nil


override func viewDidLoad() {
    super.viewDidLoad()

    guard let url = URL(string: "http://ifunnyvlogger.wixsite.com/ifunnyvlogger/app-twitter") else { return }

    webView = WKWebView(frame: self.view.frame)
    webView.translatesAutoresizingMaskIntoConstraints = false
    webView.isUserInteractionEnabled = true
    webView.navigationDelegate = self

    self.view.addSubview(self.webView)

    let request = URLRequest(url: url)
    webView.load(request)

}


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

    // Check if a link was clicked
    if navigationAction.navigationType == .linkActivated {

        // Verify the url
        guard let url = navigationAction.request.url else { return }
        let shared = UIApplication.shared

        // Check if opening in Safari is allowd
        if shared.canOpenURL(url) {

            // Ask the user if they would like to open link in Safari
            let alert = UIAlertController(title: "Do you want to open Safari?", message: nil, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (alert: UIAlertAction) -> Void in
                // User wants to open in Safari
                shared.open(url, options: [:], completionHandler: nil)
            }))
            alert.addAction(UIAlertAction(title: "Opps, no.", style: .cancel, handler: nil))

            present(alert, animated: true, completion: nil)

        }
        decisionHandler(.cancel)
    }
    decisionHandler(.allow)
}

func webViewDidStartLoad(_ : WKWebView) {
    Activity.startAnimating()
}

func webViewDidFinishLoad(_ : WKWebView) {
    Activity.startAnimating()
}

我正在使用 xcode 8 和 swift 3 创建一个 IOS 应用程序

【问题讨论】:

  • 你有什么问题?
  • 我需要帮助将活动指示器添加到我的 WKWebView 我希望它出现在 webview 加载时出现的位置,并且在完成加载时消失,它消失了。你能给我一些代码吗?

标签: ios swift3 wkwebview uiactivityindicatorview


【解决方案1】:

请尝试下面的代码,它对我来说工作正常,如果有任何问题,请提前告诉我。

import UIKit
import WebKit

class WebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

@IBOutlet weak var contentView: UIView!
@IBOutlet weak var activityIndicatorView: UIActivityIndicatorView!

override func viewDidLoad() {
    super.viewDidLoad()

    setupView()
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    self.setupWebView()
    self.loadData()
}

fileprivate func setupView() {

    self.contentView.isHidden = true
    self.activityIndicatorView.startAnimating()
}

fileprivate func setupWebView() {

    let webConfiguration = WKWebViewConfiguration()

    webView = WKWebView(frame: contentView.bounds, configuration: webConfiguration)
    webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    self.contentView.addSubview(webView)
    self.webView.allowsBackForwardNavigationGestures = true
    webView.uiDelegate = self
    webView.navigationDelegate = self
}

fileprivate func loadData() {

    if let url = URL(string: "http://google.com") {

        /// For loading PDF content 
        if contentType == .pdf {

              if let data = try? Data(contentsOf: url) {
                   self.webView.load(data, mimeType: "application/pdf", characterEncodingName: "", baseURL: url)
              }
        } else {

           let request = URLRequest(url: url)
           webView.load(request)
        }  
   }
}

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

    activityIndicatorView.stopAnimating()
    self.contentView.isHidden = false
}

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

【讨论】:

  • 虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。
【解决方案2】:

请,下面的代码工作正常。

@IBOutlet weak var Activity: UIActivityIndicatorView!
var webView : WKWebView!
@IBOutlet var containerView: UIView? = nil

override func viewDidLoad() {
    super.viewDidLoad()
    
    guard let url = URL(string: "http://www.facebook.com") else { return }
    webView = WKWebView(frame: self.view.frame)
    webView.translatesAutoresizingMaskIntoConstraints = false
    webView.isUserInteractionEnabled = true
    self.view.addSubview(self.webView)
    let request = URLRequest(url: url)
    webView.load(request)
    
    // add activity
    self.webView.addSubview(self.Activity)
    self.Activity.startAnimating()
    self.webView.navigationDelegate = self
    self.Activity.hidesWhenStopped = true
    
}

在下面实现这两个委托方法:

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

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

如果它不起作用,请告诉我。

【讨论】:

  • 活动指示器工作,但网页视图内容未加载。
  • 可以分享网址吗?
  • 这个解决方案正是我所需要的,但我很好奇@Sandy:为什么我必须将 ActivityIndi​​cator 作为子视图添加到 WKWebView 而不是将其作为顶部子视图添加到主视图(使用 bringSubview(toFront:) 方法)。我无论如何都不是专家,但乍一看,这两种解决方案似乎都应该有效
  • 为什么webView.navigationDelegate = self 被添加了两次?
【解决方案3】:
import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {

var webView: WKWebView!
var activityIndicator: UIActivityIndicatorView!

override func viewDidLoad() {
    webView = WKWebView(frame: CGRect.zero)
    webView.navigationDelegate = self;
    webView.uiDelegate = self


    activityIndicator = UIActivityIndicatorView()
    activityIndicator.hidesWhenStopped = true
    activityIndicator.center = self.view.center
    activityIndicator.style = UIActivityIndicatorView.Style.large

    webView.addSubview(activityIndicator)
    view = webView

    let load_url = URL(string: "https://google.com/")!
    webView.load(URLRequest(url: load_url))
    activityIndicator.startAnimating()

    let refresh = UIBarButtonItem(barButtonSystemItem: .refresh, target: webView, action: #selector(webView.reload))
    toolbarItems = [refresh]
    navigationController?.isToolbarHidden = false
}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    title = webView.title
    activityIndicator.stopAnimating()
}

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

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

【讨论】:

  • 虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。
【解决方案4】:

Swift 5 版本

这个概念很简单,可以移植到早期的 swift 版本。

这是一个我们可以在任何需要 web 视图的地方用作父类的类。

import UIKit
import WebKit

class CustomWebViewController: UIViewController, WKNavigationDelegate {
    var activityIndicator: UIActivityIndicatorView!

    override func viewDidLoad() {
        super.viewDidLoad()

        activityIndicator = UIActivityIndicatorView()
        activityIndicator.center = self.view.center
        activityIndicator.hidesWhenStopped = true
        activityIndicator.style = .gray
        activityIndicator.isHidden = true

        view.addSubview(activityIndicator)
    }

    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        activityIndicator.isHidden = false
        activityIndicator.startAnimating()
    }

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        activityIndicator.stopAnimating()
        activityIndicator.isHidden = true
    }
}

如果我们有一个带有 webview 的 UIViewController,我们可以从 CustomWebViewController 继承,它会为我们处理剩下的事情。记得连接webview IBOutlet。

import UIKit
import WebKit

class FirstViewController: CustomWebViewController {

    @IBOutlet var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        webView.navigationDelegate = self

        let url = URL(string: "https://google.com")
        webView.load(URLRequest(url: url!))
    }
}

【讨论】:

    【解决方案5】:
    import UIKit
    import WebKit
    
    class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {
    
        var webView: WKWebView!
        var activityIndicator: UIActivityIndicatorView!
    
        override func viewDidLoad() {
            webView = WKWebView(frame: CGRect.zero)
            webView.navigationDelegate = self
            webView.uiDelegate = self
    
            view.addSubview(webView)
    
            activityIndicator = UIActivityIndicatorView()
            activityIndicator.center = self.view.center
            activityIndicator.hidesWhenStopped = true
            activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
    
            view.addSubview(activityIndicator)
    
            webView.load(URLRequest(url: URL(string: "http://google.com")!))
        }
    
        func showActivityIndicator(show: Bool) {
            if show {
                activityIndicator.startAnimating()
            } else {
                activityIndicator.stopAnimating()
            }
        }
    
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            showActivityIndicator(show: false)
        }
    
        func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
            showActivityIndicator(show: true)
        }
    
        func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
            showActivityIndicator(show: false)
        }
    }
    

    【讨论】:

    • 这是更正确的方法,因为它处理WKWebView页面之间的导航
    • WKUIDelegate 不是必需的。示例中给出的委托方法来自 WKNavigationDelegate。
    【解决方案6】:

    viewDidLoad 中,您需要将activityIndicator 添加为subView,就像您为webView 所做的那样。由于它是一个插座,请确保 activityIndicator 位于您的 webView 之上,您应该很高兴。当webView 停止加载时,您还想将activity.hidden 设置为true

    将“活动”插座小写也是一个很好的经验法则。

    override func viewDidLoad() {
    super.viewDidLoad()
    self.view.addSubview(self.Activity)
    
    guard let url = URL(string: "http://ifunnyvlogger.wixsite.com/ifunnyvlogger/app-twitter") else { return }
    
    webView = WKWebView(frame: self.view.frame)
    webView.translatesAutoresizingMaskIntoConstraints = false
    webView.isUserInteractionEnabled = true
    webView.navigationDelegate = self
    
    self.view.addSubview(self.webView)
    
    
    let request = URLRequest(url: url)
    webView.load(request)
    

    您还可以在webViewDidFinishLoad() 中调用activity.startAnimating。确保在webView 完成加载时调用activity.stopAnimating()。编码愉快!

        func webViewDidFinishLoad(_ : WKWebView) {
        Activity.stopAnimating()
        Activity.hidden = true
    }
    

    【讨论】:

    • 这是唯一适合我的版本。使用选中标记的版本,当我将活动指示器水平/垂直居中时,我的网页没有显示。这按预期工作。
    猜你喜欢
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多