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)
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
}
}
}
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.
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)
}
Why not use
loadRequest(_ request: URLRequest, progress: ((UInt, Int64, Int64) -> Swift.Void)?, success: ((HTTPURLResponse, String) -> String)?, failure: ((Error) -> Swift.Void)? = nil)