Issue with programmatically adding ActivityIndicator with WKWebView, not appearing - swift

My code successfully loads the web page that I want it to; however, I'm having issues adding my activity indicator for while it is loading.
I am relatively new to swift, so I was reading other stackexchange examples. I created a UIActivityIndicator, set it in the override func, but it doesn't show up.
The webpage loads fine. Here is the runnable code.
import UIKit
import WebKit
class FeedbackWebViewController: UIViewController, WKNavigationDelegate {
let indicator = UIActivityIndicatorView(style: .gray)
var webView: WKWebView!
override func loadView() {
webView = WKWebView()
webView.navigationDelegate = self
indicator.center = webView.center
indicator.hidesWhenStopped = true
webView.addSubview(indicator)
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://www.apple.com")!
webView.load(URLRequest(url: url))
webView.allowsBackForwardNavigationGestures = true
self.indicator.startAnimating()
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
indicator.stopAnimating()
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
indicator.stopAnimating()
}
}

DONT override loadView. bad things may happen.
move code in didLoad. it should work.

try to put the related 3 lines to viewDidAppear rather than viewDidLoad. It works for me.

Related

WKWebView not displaying after successful load, only seeing black screen

I'm new to swift & am attempting to open a login page, login, use the WKNavigationDelegate to get the redirect uri and save the response. I was able to open the url using UIApplication.shared.open but attempting to hit the url using WKWebview, I am getting a loaded response but no view appears.
Am I not declarling the view correctly or is WKWebView not supposed to be used in that manner? This is the code i'm running, its building succesfully and responding that its 'loaded'. Any help would be be appreciated thanks.
import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
// The webview
var webViewObj: WKWebView!
var webNav: WKNavigation!
// this calls the dbhelper to create a db and a table
let db = DBHelper()
var list = [DBGrade]()
override func loadView() {
super.loadView()
let webConfiguration = WKWebViewConfiguration()
webViewObj = WKWebView(frame: .zero, configuration: webConfiguration)
}
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://www.hackingwithswift.com")
let request = URLRequest(url: url!)
webViewObj.navigationDelegate = self
self.webViewObj.uiDelegate = self
webViewObj.load(request)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("loaded")
}
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if navigationAction.targetFrame == nil {
webView.load(navigationAction.request)
}
return nil
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
let hostStr = String(describing: navigationAction.request.url)
let host = hostStr
if host.range(of: "hackingwithswift.com") != nil {
decisionHandler(.allow)
print("did it")
return
}
else{
decisionHandler(.cancel)
}
}
}
So moving my delcaration of 'self.webViewObj.uiDelegate = self' & adding 'view = webViewObj' to the loadView() function worked & I'm able to see the webpage appear.

How to add back button History in Xcode using swift language

First of all I'm new in swift. I have a WebView app for iOS device using swift language , can add button back to previous page ?
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
var webView: WKWebView!
override func loadView() {
webView = WKWebView()
webView.navigationDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://google.com/")!
webView.load(URLRequest(url: url))
webView.allowsBackForwardNavigationGestures = true
let statusBarFrame = UIApplication.shared.statusBarFrame
let statusBarView = UIView(frame: statusBarFrame)
self.view.addSubview(statusBarView)
statusBarView.backgroundColor = .systemBackground
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
title = webView.title
}
}

Application starting in webview xcode 9

Pretty new to swift & xcode 9. I have my webview code working and displaying the proper link, but it opens the app with it. I have a few different controllers before it should be displayed (ultimately button triggered). When I have this code in, it doesn't change the default view controller as link, it simply loads the webview right away. Any help would be greatly appreciated!
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
override func loadView() {
webView = WKWebView()
webView.navigationDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
// 1
let url = URL(string: "https://google.com")!
webView.load(URLRequest(url: url))
// 2
let refresh = UIBarButtonItem(barButtonSystemItem: .refresh, target: webView, action: #selector(webView.reload))
toolbarItems = [refresh]
navigationController?.isToolbarHidden = false
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
title = webView.title
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

UIActivityIndicator doesn't hide after loading page in WKWebView

I am trying to create a WKWebView app with a UIActivityIndicator (in Xcode 9). Below is my code, but when I try to simulate it, the activity indicator doesn't stop, neither hide.
import UIKit
import WebKit
class ViewController: UIViewController {
#IBOutlet var loader: UIActivityIndicatorView!
#IBOutlet var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "http://www.amritvani.nl")
let request = URLRequest(url: url!)
webView.navigationDelegate = self as? WKNavigationDelegate
webView.load(request)
}
func webViewDidStartLoad(webView: WKWebView){
loader.startAnimating()
}
func webViewDidFinishLoad(webView: WKWebView){
loader.stopAnimating()
loader.hidesWhenStopped = true
}
}
Could someone help me with this problem?
Your delegate methods are wrong. Replace webViewDidStartLoad(webView:) with this:
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
loader.startAnimating()
}
...and webViewDidFinishLoad(webView:) with this:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
loader.stopAnimating()
}
Also, you should conform your class to WKNavigationDelegate:
class ViewController: UIViewController, WKNavigationDelegate
There are two more problems with your code. Firstly, you shouldn't cast your class to WKNavigationDelegate with as? if it already conforms to it:
webView.navigationDelegate = self
Secondly, you should set the hidesWhenStopped attribute of your activity indicator to true before stopping it, preferably in Interface Builder or in viewDidLoad. This is not crucial, but it makes much more sense if someone else reads your code and it's also superfluous if webView(_:didFinish:) executes multiple times.

Using UIActivityIndicatorView with UIWebView in Swift

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.