Progressbar WebView in Swift

2020-06-27 06:48发布

I'm writing a webapp in swift with xcode. I've a question "How can I add a progressbar that shows me the loading of each page?"

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

(Sorry for my english)

4条回答
【Aperson】
2楼-- · 2020-06-27 07:00
    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()
  }

Took me ages to figure out how to determine when a website has fully loaded and animate the progress bar according... after some hardcore googling this is the best I could come up with. lots of people saying lots of stuff most of it didn't help me.... add, and improve please let me know if you figure out something better.

查看更多
劳资没心,怎么记你
3楼-- · 2020-06-27 07:01

I am using this and looks good.

@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)
}
查看更多
霸刀☆藐视天下
4楼-- · 2020-06-27 07:02

You can find a very good answer in this post. You can just add a progress bar as a subview to your webview. The main problem is the accuracy of the progress bar. The proposed answer is to begin by animating it constantly, block it at 95% when still loading and when your request is complete, zip it all the way to 100%.

Here's a solution in Swift:

Add these properties:

//Add this progress view via Interface Builder (IBOutlet) or programatically
let myProgressView: UIProgressView

var theBool: Bool
var myTimer: NSTimer

These functions will fill the progress view. You can play with the parameters:

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
        }
    }
}
查看更多
Summer. ? 凉城
5楼-- · 2020-06-27 07:21

Why not use

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

查看更多
登录 后发表回答