UIWebView with Progress Bar

后端 未结 9 1325
攒了一身酷
攒了一身酷 2020-12-08 00:47

Hi I\'m new to programming and I\'m trying to make my first app for iPhones on Xcode. My app contains of a button which opens a UIWebView when pressed and loads up a homepag

相关标签:
9条回答
  • 2020-12-08 01:27

    I have tried the following pattern. It gave me a little bit better result. I am using WKWebview.

    @IBOutlet weak var progressView: UIProgressView! // added in storyboard
    @IBOutlet weak var webView: WKWebView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
            setupEstimatedProgressObserver()
        }
    
        // Observe the WebViewClient for estimatedProgress value
        private func setupEstimatedProgressObserver() {
            estimatedProgressObserver = webView.observe(\.estimatedProgress, options: [.new]) { [weak self] webView, _ in
                self?.progressView.progress = Float(webView.estimatedProgress)
            }
        }
    
        //When WebView load finished in WKNavigationDelegate in didFinish method we will use the following approach
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            self.progressView.progress =  1.0
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                // your code here
                 self.progressView.isHidden = true
            }
        }
    
    0 讨论(0)
  • 2020-12-08 01:29

    To have an accurate UIProgressView, you need to have some task that:

    • You can get information from while it isn't complete
    • Quantify its "completeness" as a percentage based on that information.

    Now when you are loading your UIWebView, thats not possible. And Apple doesn't do it either. Apple often uses fake UIProgressViews to give you something to look at while the page is loading. Mail also uses fake progress views. Go try it out for yourself. This is how Apple's fake progress views work:

    • The progress view starts moving at a slow, constant rate
    • If the task finishes before the bar completes, it suddenly zips across the rest to 100% before disappearing
    • If the task takes a long time, the progress view will stop at 95% and will stay there until the task is complete.

    To achieve this, you will have to animate the progressView manually. You could subclass it but that would probably be a bit advanced for you. The simplest way would be this:

    In myViewController.h

    @interface myViewController : UIViewController {
         BOOL theBool;
         //IBOutlet means you can place the progressView in Interface Builder and connect it to your code
         IBOutlet UIProgressView* myProgressView;
         NSTimer *myTimer;
    }
    @end
    

    In myViewController.m

    #import "myViewController.h"
    @implementation myViewController
    - (void)webViewDidStartLoad:(UIWebView *)webView{
         myProgressView.progress = 0;
         theBool = false;
         //0.01667 is roughly 1/60, so it will update at 60 FPS
         myTimer = [NSTimer scheduledTimerWithTimeInterval:0.01667 target:self selector:@selector(timerCallback) userInfo:nil repeats:YES];
    }
    - (void)webViewDidFinishLoad:(UIWebView *)webView{
         theBool = true;
    }
    -(void)timerCallback {
        if (theBool) {
             if (myProgressView.progress >= 1) {
                  myProgressView.hidden = true;
                  [myTimer invalidate];
             }
             else {
                  myProgressView.progress += 0.1;
             }
        }
        else {
             myProgressView.progress += 0.05;
             if (myProgressView.progress >= 0.95) {
                  myProgressView.progress = 0.95;
             }
        }
    }
    @end
    

    Then, where your task gets completed, set theBool = true; and the progress view will take care of itself. Change the values in the if statement thing to control the speed of the animation.

    0 讨论(0)
  • 2020-12-08 01:29

    Swift 2.2

    class ViewController: UIViewController,UIWebViewDelegate {
    
        @IBOutlet weak var webView: UIWebView!
        @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
        @IBOutlet weak var myProgressView: UIProgressView!
    
        var myTimer = NSTimer()
        var theBool = Bool()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let url = NSURL(string: "https://www.youtube.com")
            let request = NSURLRequest(URL: url!)
            activityIndicator.hidesWhenStopped = true
            activityIndicator.startAnimating()
            webView.loadRequest(request)
    
        }
        func timerCallback(){
            if theBool {
                if myProgressView.progress >= 1 {
                    myProgressView.hidden = true
                    myTimer.invalidate()
                }else{
                    myProgressView.progress += 0.1
                }
            }else{
                myProgressView.progress += 0.05
                if myProgressView.progress >= 0.95 {
                    myProgressView.progress = 0.95
                }
            }
        }
    
        func webViewDidStartLoad(webView: UIWebView) {
            activityIndicator.startAnimating()
            myProgressView.progress = 0
            theBool = false
            myTimer =  NSTimer.scheduledTimerWithTimeInterval(0.01667,target: self,selector: #selector(ViewController.timerCallback),userInfo: nil,repeats: true)
        }
        func webViewDidFinishLoad(webView: UIWebView) {
            activityIndicator.stopAnimating()
            theBool = true
        }
    }
    
    0 讨论(0)
  • 2020-12-08 01:32

    Apple now supplies the WebKit framework, which includes the WKWebView class which allows you to query the estimated progress using the property 'estimatedProgress', so you no longer must 'fake' the progress like you do to show a progress bar on a UIWebView.

    0 讨论(0)
  • 2020-12-08 01:34

    If anyone wants to do it in swift 3, I spent a few days trying to figure it out and finally did.

    Here is the code :)

    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)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    0 讨论(0)
  • 2020-12-08 01:35

    I would have added a comment, instead of adding an answer, but I don't yet have enough reputation to comment!

    Only a couple of days ago I asked almost exactly the same question. In that question I included the solution I came up with. My solution is more complicated than WolfLink's but it does track the real progress of loading the page, although it isn't 100% accurate. As WolfLink has said that's not possible. My question can be found here: Progress bar for UIWebView

    Note whichever way you do it you'll need to check the loading property of UIWebView to determine when the loading of the page is complete.

    0 讨论(0)
提交回复
热议问题