I'm new to use webkit.
I want to give delegate my WKWebView to my view controller, but it give me error:
Cannot assign value of type 'ViewController' to type 'WKNavigationDelegate?'
My code:
import UIKit
import WebKit
class ViewController: UIViewController {
#IBOutlet weak var webKitComponent: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
webKitComponent.navigationDelegate = self
}
}
Add
extension ViewController: WKNavigationDelegate {
private func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
debugPrint("didCommit")
}
private func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
debugPrint("didFinish")
}
private func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
debugPrint("didFail")
}
}
To add to #Sh_Khan's answer; the reason for your error is that the class ViewController doesn't conform to the protocol WKNavigationDelegate out of the box.
You need to make it conform by adding the protocol and it's required methods, as Sh_Khan showed you.
I have a web view in a view controller which is loaded from a url coming from server. The content coming inside the webview is very small and unreadable.
I've implemented all the code but I'm confused as to why it is not showing properly. This is how content is shown, content start from under the header image,
This is the code used to load the url in the webview:
func loadWeb(webURL: String) {
DispatchQueue.main.async {
let url = URL(string: webURL)
self.webView.navigationDelegate = self
self.webView.load(URLRequest(url: url!))
self.view.makeToastActivity(.center)
self.webView.uiDelegate = self
self.view.hideToastActivity()
}
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
showActivityIndicator(show: false)
self.view.hideToastActivity()
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
showActivityIndicator(show: false)
self.view.hideToastActivity()
}
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
showActivityIndicator(show: false)
self.view.hideToastActivity()
}
I've a ViewControllerWeb to show a WebView. I need nav bar to show some options to user, so I need that NavigationBar is showed.
Problem: The navigation bar is not showed.
ViewControllerWeb.swift
import UIKit
import WebKit
class ViewControllerWeb : UIViewController, WKNavigationDelegate {
#IBOutlet weak var webView: WKWebView!
#IBOutlet weak var progress: UIActivityIndicatorView!
var url : String?
override func viewDidLoad() {
self.webView.allowsBackForwardNavigationGestures = true
self.webView.navigationDelegate = self
let request = URLRequest(url: URL(string: url!)!)
self.navigationController?.navigationBar.isHidden = false
self.webView.load(request)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("didFinish")
self.progress.stopAnimating()
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
print("didiFail")
self.progress.stopAnimating()
}
func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
print("webViewWebContentProcessDidTerminate")
self.progress.stopAnimating()
}
func webView(_ webView: WKWebView,
didStartProvisionalNavigation navigation: WKNavigation!) {
print("didStartProvisionalNavigation")
self.progress.startAnimating()
}
func webView(_ webView: WKWebView,
didFailProvisionalNavigation navigation: WKNavigation!,
withError error: Error) {
print("didFailProvisional")
self.progress.stopAnimating()
}
}
Storyboard
Result on simulator iPhone7
The NavigationBar isn't showed.
Present ViewControllerWeb with UINavigationController.
// Storyboard name
let storyBoard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
// Storyboard withIdentifier
let viewController = storyBoard.instantiateViewController(withIdentifier: "ViewControllerWeb")
let navBarController = UINavigationController(rootViewController: viewController)
self.present(navBarController, animated: true, completion: nil)
Is there a way to have different actions occur when different webViews are finished loading? If I have webView1 and webView2, how can I create two independent webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) functions that get called individually for one of the webViews finishing loading?
WKNavigationDelegate or any protocol's methods can only be inherited available once per class, but you can easily figure out which instance the delegate method was called from, like so:
class YourClass: WKNavigationDelegate {
var webView1: WKWebView!
var webView2: WKWebView!
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
if (webView == self.webView1) {
print("didFinishNavigationWebView1")
} else if (webView == self.webView2) {
print("didFinishNavigationWebView2")
}
}
}
I'm trying to display an Activity Indicator View in my app to users while a url is being loaded into a WebView. I've tried toying with activity.startAnimating/activity.stopAnimating and tried placing them in functions, etc. but have not had any luck.
The best I have been able to get is the Activity Indicator to appear and animate, but then not stop animating or hide once my url is loaded, so it continues spinning on top of the web page.
In other situations, when trying to move around activity.startAnimating, I have encountered the "Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)" issue. I have "Hides when Stopped" checked in the attributes inspector, I know that my url is valid, and I have created IBOutlets for the Interface Builder Elements.
Bear with me; I'm relatively new to Swift. Here's my code:
class HighchartsController: UIViewController {
#IBOutlet weak var HighchartsView: UIWebView!
#IBOutlet weak var activity: UIActivityIndicatorView!
#IBOutlet weak var saveButton: UIBarButtonItem!
#IBOutlet weak var highchartsMenu: UIBarButtonItem!
override func viewDidLoad()
{
super.viewDidLoad()
if self.revealViewController() != nil {
highchartsMenu.target = self.revealViewController()
highchartsMenu.action = "revealToggle:"
loadAddress()
}
}
func loadAddress() {
let url = NSURL (string: "http://google.com/flights")
let request = NSURLRequest (URL: url!)
HighchartsView.loadRequest(request)
println("Webpage Loaded Successfully")
}
}
And I have tried using different functions such as
webViewDidStartLoad(_ :UIWebView){
activity.startAnimating()
NSLog("Webview load has started")
}
webViewDidFinishLoad(_ :UIWebView){
activity.stopAnimating()
NSLog("Webview load had finished")
}
First of all, i don't see delegation of UIWebView.
Realize your behaviour related to delegation processes.
UIWebViewDelegate has four methods, but use for this way just three:
Swift 4
func webViewDidStartLoad(_ webView: UIWebView) // show indicator
func webViewDidFinishLoad(_ webView: UIWebView) // hide indicator
func webView(_ webView: UIWebView, didFailLoadWithError error: Error) // hide indicator
Swift 3
func webViewDidStartLoad(webView: UIWebView!) // show indicator
func webViewDidFinishLoad(webView: UIWebView!) // hide indicator
func webView(webView: UIWebView!, didFailLoadWithError error: NSError!) // hide indicator
*WKWebView equivalent of dimpiax answer. Use WKNavigationDelegate
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) // show indicator
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) // hide indicator
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) // hide indicator*
You need to add UIWebViewDelegate to your class like so.
class HighchartsController: UIViewController, UIWebViewDelegate {
You will also need to assign your webView delegate to self in viewDidLoad function like so.
HighchartsView.delegate = self
I'm sure you figured it out by now but you need to wire up your UIWebView to set its delegate as your UIViewController in the storyboard by control-dragging.
The following are three simple steps that I always follow in Xcode 8 / Swift 3 / iOS 10 in order to implement UIWebView page loading indicator:
Step 1. Create outlets for the Web View and Load Indicator in the ViewController class. For example:
#IBOutlet var loadSpinner: UIActivityIndicatorView!
#IBOutlet weak var webView: UIWebView!
These two lines should have non-empty dots to the left of them.
Step 2. In the Storyboard: Control-drag the WebView to the ViewController and choose "delegate" from the menu. As GarySabo correctly pointed out, without this step, the indicator will appear but won't work!
Step 3. Add the following code to your ViewController class:
func webViewDidStartLoad(_ : UIWebView) {
loadSpinner.startAnimating()
}
func webViewDidFinishLoad(_ : UIWebView) {
loadSpinner.stopAnimating()
}
If you are using WKWebView, set WKNavigationDelegate like
webView.navigationDelegate = self
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
//Show loader
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
//Hide loader
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
//Hide loader
}
extension WebViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
print("Start loading")
LoadingIndicator.show()
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("End loading")
LoadingIndicator.hide()
}
}
Call the delegate methods. It's working fine.