Swift中的进度条WebView

4

我正在使用Xcode编写Swift的Web应用程序。

我有一个问题:"如何添加一个进度条,显示每个页面的加载进度?"

@IBOutlet var webView: UIWebView!
override func viewDidLoad() {
   super.viewDidLoad()
   let url = NSURL(string: "http://stackoverflow.com")
   let request = NSURLRequest(URL: url)
   webView.loadRequest(request)
}

很抱歉我的英语不好

5个回答

16
你可以在这篇帖子中找到一个很好的答案:链接。你只需要将进度条作为Webview的子视图添加即可。主要问题是进度条的准确性。提议的解决方案是始终以动画形式显示它,在仍在加载时将其阻塞在95%,并在请求完成时将其缩放到100%。
这里是Swift中的一个解决方案:
添加这些属性:
//Add this progress view via Interface Builder (IBOutlet) or programatically
let myProgressView: UIProgressView

var theBool: Bool
var myTimer: NSTimer

这些函数将填充进度视图。您可以尝试调整参数:

func funcToCallWhenStartLoadingYourWebview() {
    self.myProgressView.progress = 0.0
    self.theBool = false
    self.myTimer = NSTimer.scheduledTimerWithTimeInterval(0.01667, target: self, selector: "timerCallback", userInfo: nil, repeats: true)
}

func funcToCallCalledWhenUIWebViewFinishesLoading() {
    self.theBool = true
}

func timerCallback() {
    if self.theBool {
        if self.myProgressView.progress >= 1 {
            self.myProgressView.hidden = true
            self.myTimer.invalidate()
        } else {
            self.myProgressView.progress += 0.1
        }
    } else {
        self.myProgressView.progress += 0.05
        if self.myProgressView.progress >= 0.95 {
            self.myProgressView.progress = 0.95
        }
    }
}

谢谢您的回答,但我需要适用于Swift的代码,我该如何在我的Swift应用程序中使用它? - Mirko Brombin
嘿,我添加了一些代码。你只需要将进度视图添加到你的用户界面中即可。 - Starscream
这些应该添加在哪里? var theBool: Bool var myTimer: NSTimer如果我将它们添加到 ViewController 类中,会出现错误:class ViewController 没有初始化器。 - Mirko Brombin
这是因为如果你将它们添加到一个类中,它们需要在初始化时被初始化。var theBool: Bool = false var myTimer = NSTimer() - Starscream
另一个选项,而不是定义funcToCallCalledWhenUIWebViewFinishesLoading(),是在控制器中实现UIWebViewDelegate并覆盖webViewDidFinishLoad函数。您还需要将webview的代理设置为控制器才能使其正常工作。 - Achintya Ashok
我在想为什么它只出现一次:在funcToCallWhenStartLoadingYourWebview中缺少self.myProgressView.isHidden = false - FrugalResolution

4
    var theBool: Bool
    var myTimer: NSTimer
    var didFinishTimer: NSTimer


    required init(coder aDecoder: NSCoder) {
        self.theBool = false
        self.myTimer = NSTimer()
        self.didFinishTimer = NSTimer()

        super.init(coder: aDecoder)
    }
           func startAnimatingProgressBar() {
            self.theBool = false
            myProgressView.hidden = false
            myProgressView.alpha = 0
            UIView.animateWithDuration(0.2, animations: { () -> Void in
                self.myProgressView.alpha = 0.6
            })
            self.myProgressView.progress = 0.0

            //Tweek this number to alter the main speed of the progress bar
            var number = drand48() / 80;
//            println("startAnimatingProgressBar|\(number)")

            self.myTimer = NSTimer.scheduledTimerWithTimeInterval(number, target: self, selector: "timerCallback", userInfo: nil, repeats: true)
//            println("myTimer|\(myTimer)")
    }

    func finishAnimatingProgressBar() {
        self.theBool = true
    }

    func timerCallback() {
        if self.theBool {
            if self.myProgressView.progress >= 1 {
                UIView.animateWithDuration(0.2, animations: { () -> Void in
                    self.myProgressView.alpha = 0

//                    }, completion: { (success:Bool) -> Void in
//                        self.myProgressView.hidden = true
                })
                self.myTimer.invalidate()
            } else {
                //Loaded and zoom to finish
                var number = drand48() / 40
//                println("finished:\(number)")

                self.myProgressView.progress += Float(number)
            }

        } else {
            //Start slow
            if self.myProgressView.progress >= 0.00 && self.myProgressView.progress <= 0.10 {
                var number = drand48() / 8000;
//                println("Start:\(number)")

                self.myProgressView.progress += Float(number)
                //Middle speed up a bit
            } else if self.myProgressView.progress >= 0.10 && self.myProgressView.progress <= 0.42 {
                var smallerNumber = drand48() / 2000;
                self.myProgressView.progress += Float(smallerNumber)
//                println("Middle:\(smallerNumber)")

                //slow it down again
            } else if myProgressView.progress >= 0.42 && self.myProgressView.progress <= 0.80 {
                var superSmallNumber = drand48() / 8000;
                self.myProgressView.progress += Float(superSmallNumber)
//                println("slow it down:\(superSmallNumber)")

                //Stop it
            } else if myProgressView.progress == 0.80 {
                println("Stop:\(myProgressView.progress)")
                self.myProgressView.progress = 0.80
            }
        }
    }


    var webViewLoads = 0
    var webViewDidStart:Int = 0
    var webViewDidFinish:Int = 0

  func webViewDidStartLoad(webView: UIWebView) {


    webViewDidStart++
    webViewLoads++

    if webViewLoads <= 1 {
        startAnimatingProgressBar()
    }

    println("webViewDidStartNumber: = \(webViewDidStart)")
    println("webViewLoadsStart: = \(webViewLoads)")

//    println("webViewDidStartLoad")

    UIApplication.sharedApplication().networkActivityIndicatorVisible = true
    updateToolbarItems()
  }

  func webViewDidFinishLoad(webView: UIWebView) {

        webViewLoads--
        webViewDidFinish++

        println("webViewDidFinishLoad \(webViewDidFinish)")

    if webViewLoads == 0 {
        finishAnimatingProgressBar()
//        println("webViewLoads \(webViewLoads)")
        return
    }
    getWebsiteInfo()
    UIApplication.sharedApplication().networkActivityIndicatorVisible = false

    updateToolbarItems()

  func webView(webView: UIWebView, didFailLoadWithError error: NSError) {
    theBool = true
    webViewLoads = 0
    UIApplication.sharedApplication().networkActivityIndicatorVisible = false

    println("didFailLoadWithError")

    updateToolbarItems()
  }

我花了很长时间才弄清楚如何确定网站何时完全加载,并根据进度条进行动画处理... 经过一些艰苦的谷歌搜索,这是我能想出的最好方法。很多人说了很多话,大部分都没有帮助到我... 如果您发现更好的方法,请添加和改进并让我知道。


这是最准确的一个。 - Hashem Aboonajmi
@HashemAboonajmi 实际上,最好的方法是使用WKWebKit或WKWebView(我记不清确切名称了)或SafariViewController。如果您需要进度条方面的帮助,请给我发消息。 - Alexander Macleod

4

我正在使用这个,看起来不错。

@IBOutlet var webView: UIWebView!
@IBOutlet var progressView: UIProgressView!
override func viewDidLoad() {
   super.viewDidLoad()
   let url = NSURL(string: "http://stackoverflow.com")
   let request = NSURLRequest(URL: url)
   webView.loadRequest(request)
   webView.delegate=self
}

func webViewDidStartLoad(_ webView: UIWebView) {

    self.progressView.setProgress(0.1, animated: false)
}


func webViewDidFinishLoad(_ webView: UIWebView) {

    self.progressView.setProgress(1.0, animated: true)
}

func webView(_ webView: UIWebView, didFailLoadWithError error: NSError?) {

    self.progressView.setProgress(1.0, animated: true)
}

2

Swift 5

@IBOutlet weak var webView: WKWebView!
@IBOutlet weak var progressView: UIProgressView!

override func viewDidLoad() {
    super.viewDidLoad()

webView.addObserver(self, forKeyPath:
                #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)
}


override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
       if keyPath == "estimatedProgress" {
           print("estimatedProgress")
           progressView.progress = Float(webView.estimatedProgress)
       }
   }

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

0
为什么不使用以下代码:

loadRequest(_ request: URLRequest, progress: ((UInt, Int64, Int64) -> Swift.Void)?, success: ((HTTPURLResponse, String) -> String)?, failure: ((Error) -> Swift.Void)? = nil)

该代码与编程有关。

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