问题
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)
回答1:
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
}
}
}
回答2:
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:
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:
Why not use
loadRequest(_ request: URLRequest, progress: ((UInt, Int64, Int64) -> Swift.Void)?, success: ((HTTPURLResponse, String) -> String)?, failure: ((Error) -> Swift.Void)? = nil)
来源:https://stackoverflow.com/questions/28147096/progressbar-webview-in-swift