Progress Bar in Cocoa

北城余情 提交于 2020-01-15 11:00:12

问题


I have a very simple application that contains a WebView. This webview loads an HTML5 app and it takes some time while the content is being built inside the webview.

I would like to show a progress bar until the content finishes loading and show the webview when the content is ready. It takes roughly 10 seconds.

??


回答1:


Swift 2.2

override func viewDidLoad() {
    super.viewDidLoad()

    webView.frameLoadDelegate = self
    webView.addObserver(self, forKeyPath: "estimatedProgress", options: .New, context: nil) // add observer for key path
}

/// Observer listening for progress changes
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if (keyPath == "estimatedProgress") { // listen to changes and updated view
        if self.webView.estimatedProgress == 0 { return }
        // All UI operations always in main thread
        dispatch_async(dispatch_get_main_queue(), {
            // *100 because progressIndicator in Mac OS wants values from 0 to 100
            self.progressIndicator.doubleValue = self.webView.estimatedProgress * 100
        })
    }
}

/// Hide progress indicator on finish
func webView(sender: WebView!, didFinishLoadForFrame frame: WebFrame!) {
    dispatch_async(dispatch_get_main_queue(), { self.progressIndicator.hidden = true })
}

/// Show progress indicator on start page loading
func webView(sender: WebView!, didStartProvisionalLoadForFrame frame: WebFrame!) {
    dispatch_async(dispatch_get_main_queue(), { self.progressIndicator.hidden = false })
}

Swift 3

override func viewWillAppear() {
    super.viewWillAppear()
    webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
}


override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if (keyPath == "estimatedProgress") { // listen to changes and updated view
        DispatchQueue.main.async {
            // Here you can do set your actions on progress update
            // E.g.: someProgressBar.doubleValue = self.webView.estimatedProgress * 100
        }
    }
}

override func viewWillDisappear() {
    super.viewWillDisappear()
    webView.removeObserver(self, forKeyPath: "estimatedProgress")
}

Full solution

I've created Swift 3 Cocoa code snippet with NSViewController with embedded WKWebViewController and NSProgressIndicator so you can look at live example.




回答2:


You need to create a class that conforms to the WebFrameLoadDelegate protocol and set it as the delegate for your WebView.

Delegates in Cocoa are its callback pattern. You make a class that conforms to a protocol, implementing the required messages and whatever optional messages you need, add that class as a delegate to the main class, in your case the WebView, and your delegate gets messages whenever things happen in the main class.

From your delegate you could create a timer that repeats ever 1/10th of a second and sends the main WebView the message - (double)estimatedProgress to update your progress bar. Once the view is loaded invalidate the timer and remove the progress bar.




回答3:


WebKit posts WebViewProgressEstimateChangedNotification and friends to give you this information



来源:https://stackoverflow.com/questions/9701273/progress-bar-in-cocoa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!