1

I want to make a loading bar in Swift 3 for my iOS project. I'm doing a web view for the moment and need to do this loading bar to show in between the actions. I know it is fake loading bar and I saw code in Objective-C and tried to make something out of it in Swift but I'm afraid that my logic is wrong, since I'm new in Swift.

The problem I'm having is that I don't acctually know if I set vars theBool and timer to the right place and I dont know how to use Timer().

And to tell you what I see when I run the app, Progress bar is showing the whole time, but it's not loading.

This is my code so far

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var webView: UIWebView!
    @IBOutlet weak var progressView: UIProgressView!

    var theBool = false
    var timer = Timer()

    override func viewDidLoad() {
        super.viewDidLoad()

        progressView.progress = 0.0

        //Reading the webview
        let websiteURL = URL(string: "http://google.com")
        let websiteURLRequest = URLRequest(url: websiteURL!)
        webView.loadRequest(websiteURLRequest)
    }

    func webViewDidFinishLoad (){
        if webView.isLoading == true {
        theBool = true
        }
    }

    func handleProgress () {
        if (theBool){
            if (progressView.progress >= 1) {
                progressView.isHidden = true
                timer.invalidate()
            } else {
                progressView.progress += 0.1
            }
        } else {
            progressView.progress += 0.05
            if (progressView.progress >= 0.95) {
                progressView.progress = 0.95
            }
        }
    }

    /*
    func addValsToProgress () ->String {
        if (webViewLoading() == true) {
            view.progressView.setProgre
        }
    }
    */
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Matej Marić
  • 125
  • 1
  • 12
  • I don't see anywhere where you actually handle the progress change, like a download progress handler. Are you just doing this as a dummy process? – Pierce Jan 28 '17 at 17:28
  • If all you want to do is start a timer to call that dummy method, you should say `yourTimerName = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(handleProgress), userInfo: nil, repeats: true)` – Pierce Jan 28 '17 at 17:30
  • I've read about loading bars and found out that all of those loading bars are actually fake and there was some code in objective-c on how to make that progress bar which loads till 95% then stops and waits for the page to load. when the page loads it fills the last 5% very fast and then shows the page. That's what I want, except if you know a way to get the process time when I tap on something and calculate remaining time of the load and display it – Matej Marić Jan 30 '17 at 12:03

3 Answers3

2

Based on the code that you provided, you need to initialize the timer with a time interval and an action. That way when the timer is invoked, it calls handleProgress. The timer should fire when the loading state begins and will periodically call handleProgress until loading has finished. At that point, the timer will be invalidated and will stop calling handleProgress.

See https://developer.apple.com/reference/foundation/timer for how to do that.

Darryl Johnson
  • 431
  • 3
  • 10
2

So after a few tries with the solutions you posted, I found an answer. It's so simple that I was ashamed.

It works like a charm. Thank you all for your answers :)

@IBOutlet var webView: UIWebView!
@IBOutlet var progressView: UIProgressView!

override func viewDidLoad() {
    super.viewDidLoad()
    let url = NSURL(string: "http://google.com")
    let request = NSURLRequest(url: url as! URL)
    webView.loadRequest(request as URLRequest)
    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: Error) {

    self.progressView.setProgress(1.0, animated: true)
}
Matej Marić
  • 125
  • 1
  • 12
  • And it shows a changing Progress while a Long loading? Or only at the when it finished? – muescha Jan 30 '17 at 21:28
  • It is a "Fake" Progress with an Animation to 1 on finished load? – muescha Jan 30 '17 at 21:31
  • But sometimes it is enough only to have something to entertain the user and there is not the need of real progress data. Thumbs up for this easy solution. Thx for sharing :) – muescha Jan 30 '17 at 21:33
  • I wanted to do it the proper way, but cant find a way to get the predicted time to finish the process. I've read about how to do it and found out that people actually fake it with this method or some other methods similar to this one. I've even tried to implement them but since they are for older versions of swift or for objective c, I couldn't make any of them work except this one. I'm also a bit disappointed that the right way to do this is so hard to find :/ – Matej Marić Jan 31 '17 at 07:10
1

you don't need a fake loading bar. you can get it work with WKWebView

KVO Observer

you can place a KVO observer to this value:

https://developer.apple.com/reference/webkit/wkwebview/1415007-estimatedprogress

YouTube video: https://www.youtube.com/watch?v=vd3Imcc7ctw

one older example here: https://www.hackingwithswift.com/example-code/wkwebview/how-to-monitor-wkwebview-page-load-progress-using-key-value-observing

more examples on github search: https://github.com/search?l=Swift&o=desc&q=estimatedProgress+addObserver&s=indexed&type=Code&utf8=%E2%9C%93

Delegates

WKNavigationDelegate

https://developer.apple.com/reference/webkit/wknavigationdelegate

also there are some delegate callbacks here:

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

see https://developer.apple.com/reference/webkit/wknavigationdelegate/1455629-webview

PS: there is also WKUIDelegate - but there are not so interesting methods

https://developer.apple.com/reference/webkit/wkuidelegate

muescha
  • 1,544
  • 2
  • 12
  • 22