Trying to implement a delegate and it isn't working [duplicate] - ios

I have a view controller for a webview, setup through KINWebBrowser.
I've tried several ways to get these methods to execute:
func webViewDidStartLoad(webView: UIWebView) {
print("Strat Loading")
}
func webViewDidFinishLoad(webView: UIWebView) {
print("Finish Loading")
}
func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
print(error?.localizedDescription)
}
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
return true
}
override func webViewDidFinishLoad(_ webView: UIWebView) {
super.webViewDidFinishLoad(webView)
print("Finish Loading 2")
}
But nothing seems to be working.
My class definition seems normal: class WebBrowserViewController: KINWebBrowserViewController, NavigationProtocol {
But no matter what I do - override func or not, no logger or print statement I put in these functions seems to be executed.
What am I doing wrong? I am trying to create an event that will listen to when all of the web content is loaded so I can stop having a loading spinner appear.
EDIT: Adding delegate information:
When I have tried to add a delegate to viewDidLoad():
webView.delegate = self
I have gotten the following error:
Ambiguous reference to member 'webView(_:decidePolicyFor:decisionHandler:)'
This is my viewDidLoad() without the delegate setting:
override func viewDidLoad() {
super.viewDidLoad()
pointsNavigationItem = addPointsButtonToNavigation()
self.showsURLInNavigationBar = false
self.showsPageTitleInNavigationBar = false;
self.tintColor = UIColor.navText
self.barTintColor = .navBackground
}
I'm not sure that KinWebBrowser does delegation the same way?
Added the KINWebBrowserDelegate to the class definition and added the following methods:
func webBrowser(_ webBrowser: KINWebBrowserViewController!, didFailToLoad URL: URL!, error: Error!) {
print("DEBUG 5")
}
func webBrowserViewControllerWillDismiss(_ viewController: KINWebBrowserViewController!) {
print("DEBUG 1")
}
func webBrowser(_ webBrowser: KINWebBrowserViewController!, didStartLoading URL: URL!) {
print("DEBUG 2")
}
func webBrowser(_ webBrowser: KINWebBrowserViewController!, didFinishLoading URL: URL!) {
print("DEBUG 3")
}
func didChangeValue<Value>(for keyPath: KeyPath<WebBrowserViewController, Value>) {
print("DEBUG 4")
}
None of the debugs are getting called in the log.

Those are the UIWebView delegate methods, however from the KINWebBrowser page you should probably be using the KINWebBrowserDelegate protocol
(void)webBrowser:(KINWebBrowserViewController *)webBrowser didStartLoadingURL:(NSURL *)URL;
(void)webBrowser:(KINWebBrowserViewController *)webBrowser didFinishLoadingURL:(NSURL *)URL;
(void)webBrowser:(KINWebBrowserViewController *)webBrowser didFailToLoadURL:(NSURL *)URL withError:(NSError *)error;

Related

webViewDidFinishLoad() does not appear to be running in Swift

I have a view controller for a webview, setup through KINWebBrowser.
I've tried several ways to get these methods to execute:
func webViewDidStartLoad(webView: UIWebView) {
print("Strat Loading")
}
func webViewDidFinishLoad(webView: UIWebView) {
print("Finish Loading")
}
func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
print(error?.localizedDescription)
}
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
return true
}
override func webViewDidFinishLoad(_ webView: UIWebView) {
super.webViewDidFinishLoad(webView)
print("Finish Loading 2")
}
But nothing seems to be working.
My class definition seems normal: class WebBrowserViewController: KINWebBrowserViewController, NavigationProtocol {
But no matter what I do - override func or not, no logger or print statement I put in these functions seems to be executed.
What am I doing wrong? I am trying to create an event that will listen to when all of the web content is loaded so I can stop having a loading spinner appear.
EDIT: Adding delegate information:
When I have tried to add a delegate to viewDidLoad():
webView.delegate = self
I have gotten the following error:
Ambiguous reference to member 'webView(_:decidePolicyFor:decisionHandler:)'
This is my viewDidLoad() without the delegate setting:
override func viewDidLoad() {
super.viewDidLoad()
pointsNavigationItem = addPointsButtonToNavigation()
self.showsURLInNavigationBar = false
self.showsPageTitleInNavigationBar = false;
self.tintColor = UIColor.navText
self.barTintColor = .navBackground
}
I'm not sure that KinWebBrowser does delegation the same way?
Added the KINWebBrowserDelegate to the class definition and added the following methods:
func webBrowser(_ webBrowser: KINWebBrowserViewController!, didFailToLoad URL: URL!, error: Error!) {
print("DEBUG 5")
}
func webBrowserViewControllerWillDismiss(_ viewController: KINWebBrowserViewController!) {
print("DEBUG 1")
}
func webBrowser(_ webBrowser: KINWebBrowserViewController!, didStartLoading URL: URL!) {
print("DEBUG 2")
}
func webBrowser(_ webBrowser: KINWebBrowserViewController!, didFinishLoading URL: URL!) {
print("DEBUG 3")
}
func didChangeValue<Value>(for keyPath: KeyPath<WebBrowserViewController, Value>) {
print("DEBUG 4")
}
None of the debugs are getting called in the log.
Those are the UIWebView delegate methods, however from the KINWebBrowser page you should probably be using the KINWebBrowserDelegate protocol
(void)webBrowser:(KINWebBrowserViewController *)webBrowser didStartLoadingURL:(NSURL *)URL;
(void)webBrowser:(KINWebBrowserViewController *)webBrowser didFinishLoadingURL:(NSURL *)URL;
(void)webBrowser:(KINWebBrowserViewController *)webBrowser didFailToLoadURL:(NSURL *)URL withError:(NSError *)error;

NSURLSession/NSURLConnection HTTP load failed on Swift 4

I have xcode 9.1 with swift 4 and i'm unable to authenticate using webview anymore. here is my code :
import UIKit
protocol AuthViewControllerDelegate{
func getAccessToken(_ code: String)
}
class AuthViewController: UIViewController, NSURLConnectionDelegate {
#IBOutlet weak var navItem: UINavigationItem!
#IBOutlet weak var webView: UIWebView!
var delegate: AuthViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
var link: "https://home.nest.com/login/oauth2?client_id=…"
if let encodeURL = link.URLEncodedString(), let url = URL(string: encodeURL) {
webView.loadRequest(URLRequest(url: url))
}
}
override var preferredStatusBarStyle : UIStatusBarStyle {
return .lightContent
}
#IBAction func CancelPressed(_ sender: UIBarButtonItem) {
self.dismiss(animated: true, completion: nil)
}
func webView(_ webView: UIWebView, shouldStartLoadWithRequest request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if let url = request.url?.absoluteString, url.contains("code=") {
if let code = getQueryStringParameter(url,param: "code"){
self.dismiss(animated: true, completion: { () -> Void in
UIApplication.shared.isNetworkActivityIndicatorVisible = false
self.delegate?.getAccessToken(code)
})
}
}
return true
}
func webViewDidStartLoad(_ webView: UIWebView){
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
func webViewDidFinishLoad(_ webView: UIWebView){
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
func getQueryStringParameter(_ url: String?, param: String) -> String? {
if let url = url, let urlComponents = URLComponents(string: url), let queryItems = (urlComponents.queryItems) {
return queryItems.filter({ (item) in item.name == param }).first?.value!
}
return nil
}
}
And here is the error i'm getting in the log :
2017-11-07 20:49:30.836087+0000 TestApp[1851:1259046] TIC TCP Conn
Failed [32:0x1c0365280]: 3:-9800 Err(-9800)
2017-11-07 20:49:30.836472+0000 TestApp[1851:1259046]
NSURLSession/NSURLConnection HTTP load failed
(kCFStreamErrorDomainSSL, -9800)
2017-11-07 20:49:30.836578+0000 TestApp[1851:1259046] Task
<0A675AA1-7110-4FCC-99B2-054380D22F01>.<0> HTTP load failed (error
code: -1200 [3:-9800])
2017-11-07 20:49:30.837548+0000 TestApp[1851:1258708] NSURLConnection
finished with error - code -1200
And i already have this into my .plist file :
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
NB: The same code was working perfectly with swift 3.2
Check if your htpps:// is right, had the same problem, fixed after changing url.
Adding NSAllowsArbitraryLoads into .plist file resolves the error
NSURLConnection error - code - 1200
where my development language is Objective C.

Swift: How to wrap an async method in a synchronous method?

I'm trying to load Javascript synchronously in my WKWebView. From my research it looks like the evaluateJavaScript method is asynchronous and this is causing errors because the page would load before the JS that overrides a lot of behavior (it only works a portion of the time because of the async nature).
I've tried this but it doesn't seem to work :
extension WKWebView {
func evaluateJavaScriptSynchronously(script: String, completion: () -> Void) {
let semaphore = dispatch_semaphore_create(1)
evaluateJavaScript(script) { (result, error) in
if error == nil {
if result != nil {
print("SUCCESS")
completion()
}
} else {
print("ERROR!!!")
print(error)
print(result)
completion()
}
dispatch_semaphore_signal(semaphore)
}
let timeout = dispatch_time_t(10000)
dispatch_semaphore_wait(semaphore, timeout)
}
}
I know it's not working because the page still sometimes loads as if the JS wasn't there. Is there a similar thing I can do to synchronize the process?
You can define a WKNavigationDelegate to get notified when the page into the WKWebView has been loaded
class Controller: UIViewController, WKNavigationDelegate {
#IBOutlet var webView: WKWebView!
override func viewDidLoad() {
self.view = webView
webView.navigationDelegate = self
}
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
print("page loaded")
// <--- call your method from here
}
}
You can now call your method from within webView(wevView:didFinishNavigation:)

Activity indicator not stopping when webview has finished loading

Anyone have an idea why my activity indicator is not stopping when the webview has finished loading? Web view is delegated, UIActivityIndicatorView start animating etc, is in my code... ?
This is the relevant code:
import UIKit
class ViewController: UIViewController, UIWebViewDelegate {
#IBOutlet weak var webview: UIWebView!
#IBOutlet weak var activity: UIActivityIndicatorView!
var url = "http://apple.com"
func loadURL () {
let requestURL = NSURL(string: url)
let request = NSURLRequest(URL: requestURL!)
webview.loadRequest(request)
}
override func viewDidLoad() {
super.viewDidLoad()
loadURL()
// Do any additional setup after loading the view, typically from a nib.
webview.delegate = self;
}
func webviewDidStartLoad(_ : UIWebView){
activity.startAnimating()
NSLog("The webview is starting to load")
}
func webviewDidFinishLoad(_ : UIWebView){
activity.stopAnimating()
activity.hidden=true;
NSLog("The webview is done loading")
}
Thanks!
Mind the functions names! It's webView..., camel case :)
Are you getting "The webview is done loading"?. If not, probably the request it's taking a very long time to complete it.
However, you should implement func webView(webView: UIWebView, didFailLoadWithError error: NSError?) to detect if there's any error and stop the activity.
Actually, the correct answer is a probably combination of DAN's and iGongora's, plus a possible third reason.
The immediate problem is that even in a happy path scenario (where the webview finishes successfully) is that it should be the following (pay attention to the case of the function names webViewDidStartLoad and webViewDidFinishLoad
func webViewDidStartLoad(webView: UIWebView) {
activity.startAnimating()
NSLog("The webview is starting to load")
}
func webViewDidFinishLoad(webView: UIWebView) {
activity.stopAnimating()
activity.hidden=true;
NSLog("The webview is done loading")
}
Additionally, if the UIWebView fails, you should also stop the spinner.
func webView(webView: UIWebView!, didFailLoadWithError error: NSError!) {
activity.stopAnimating()
activity.hidden=true;
print("Webview fail with error \(error)");
}
One other possible problem would be if you have not set the delegate properly. You can do it in the viewDidLoad, or in Interface Builder.
override func viewDidLoad() {
super.viewDidLoad()
...
self.webView.delegate = self;
...
}
Run this in main queue so this will stop other wise not the code for this swift 4 and swift 3 is
Dispatchqueue.main.async{
activity.stopAnimating()
}

How to load a webview in a SWIFT based ios App

I am relatively very new to swift. Could you please help me how to load a webview in an ios app based on swift. Basically I want to load the contents of an external URL in an ios app.
Can anyone please help?
override func viewDidLoad() {
super.viewDidLoad()
let webV:UIWebView = UIWebView(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height))
webV.loadRequest(NSURLRequest(URL: NSURL(string: "http://www.google.com")))
webV.delegate = self;
self.view.addSubview(webV)}
and if you want use delegate function
func webView(webView: UIWebView!, didFailLoadWithError error: NSError!) {
print("Webview fail with error \(error)");
}
func webView(webView: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) -> Bool {
return true;
}
func webViewDidStartLoad(webView: UIWebView!) {
print("Webview started Loading")
}
func webViewDidFinishLoad(webView: UIWebView!) {
print("Webview did finish load")
Before asking your questions research what you're looking, because this question has been answered on many forums.
In the viewDidLoad() add the following code. Make sure to connect the WebView to the View and to connect the outlet.
let url = NSURL (string: "https://www.google.com");
let requestObj = NSURLRequest(URL: url!);
myWebView.loadRequest(requestObj);
}

Resources