WKNavigationDelegate occasionally doesn't get called - ios

I use a WKWebView in my app and use a native login page. Whenever the web app redirects to the login page I catch it and show the native view controller. This works perfectly fine most of the time. However, I've found that every once in a while (in production mainly) some users get shown the web app login page. It's very rare and inconsistent. I was able to see this behavior when coming back into the app after it was in the background for a while.
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
if let url = navigationAction.request.url {
if (url.absoluteString.contains("/login")) {
decisionHandler(.cancel)
// redirects to native login page
...
return
}
}
decisionHandler(.allow)
}
Also, I do set the delegate BEFORE calling load on the webview.
Any idea what might be going on and how to prevent this from happening?

Related

how do I perform tasks before loading a webview url in ios?

so I can't seem to figure out a way to perform some tasks before loading a url in ios webview.
Like in android we can use shouldOverrideUrlLoading.
#Override
public boolean shouldOverrideUrlLoading(final WebView view, String url) {
///sometask
}
but I can't find a function that does something like this in ios.
Say a user clicked on a href tag inside the webview that takes it to different page, how do I know what link that tag takes the user to? before changing the page.
Basically I want to check what url the webpage is about to load and perform extra steps according to that url.
You can use WKNavigationDelegate
set navigationDelegate in viewDidLoad
self.webView?.navigationDelegate = self
Observe URL in below navigationDelegate Method.
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
DispatchQueue.main.async {
if let urlString = navigationAction.request.url?.absoluteString{
print(urlString)
}
}
decisionHandler(.allow)
}

Prevent WKWebView From Being Able To Navigate To Specific Pages On A Website (Swift 5)

I am trying to prevent users from being able to navigate to different pages on a website by using WKNavigationDelegate and implementing the function below:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
if let urlStr = navigationAction.request.url?.absoluteString {
if urlStr == "https://random.ca/#/profile" {
decisionHandler(.cancel)
return
}
}
decisionHandler(.allow)
}
This function seems to only be called when I first load the home page of the website and when I navigate to other pages inside of this site it is not triggered and so I cannot prevent the user from navigating to those pages.
Any advice would be greatly appreciated.
I found something
Just before calling webView.load()
add this
webView.isUserInteractionEnabled = false
check this Disable links in WKWebView? for more details

WKWebview navigation response method isn't getting called upon clicking done button in a webview

I'm using WKWebview for my Swift app. For some reason, WKWebview navigation response delegate method isn't getting called when the user clicks the done button in a WKWebView. When I try the same action on the web, it redirects to the correct url.
So far I have tried clearing WKWebview cache before configuring WKWebView in viewDidLoad or if I get a memory warning. Also, ensured my info.plist allows arbitrary loads and NSExceptionAllowsInsecureHTTPLoads for testing purposes. Despite trying these things to debug, the navigation response delegate method still didn't get called.
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: #escaping (WKNavigationResponsePolicy) -> Void) {
if let webviewUrl = webView.url {
let urlString = webviewUrl.absoluteString
if urlString.contains("\(myUrlComponents)") {
self.navigationController?.popViewController(animated: true)
decisionHandler(.cancel)
return
}
}
decisionHandler(.allow)
}
I want to be able to detect a specific WKWebview url when the navigation response method gets called and go back to the previous screen.
I think you'll find that it will be called if you use the delegate function that looks identical to the one you're using except that the "decisionHandler" is a function taking WKNavigationActionPolicy as its argument.

WKWebView not loading content from iframe on a webpage

I have a WKWebView where a user goes through several pages to reach a page which contains a video from lesson.ly.
The problem is that the video will not show up at all within the webview, there is just a blank gap in the page where the video would be. However, if I open chrome on iOS, it loads just fine.
I've pinpointed the issue by debugging the HTML code. Here is a screen shot of the HTML on the webview:
And Here's a picture of the HTML on Chrome for Mac:
If you noticed, there is nothing within the iframe for the webview. I have no idea why it's not loading the data. I have enabled 'Allows Arbitrary Loads' for App Transport Security to no avail.
Any help appreciated, thanks.
Alternatively, instead of allowing specific URLs, you can check if request in question is targeting main frame or not:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Swift.Void) {
// Allow navigation for requests loading external web content resources.
guard navigationAction.targetFrame?.isMainFrame != false else {
decisionHandler(.allow)
return
}
...
}
Figured out the problem. It was all in the delegate method webView:decidePolicyForNavigationAction:decisionHandler: and because the Lessonly videos come from a different source (fast.wistia.net) I had to add that url expliclity.
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
guard let requestURL = navigationAction.request.url?.absoluteString else { return }
if requestURL.tc_contains("mydomain.lesson.ly") || requestURL.tc_contains("fast.wistia.net"){
decisionHandler(.allow)
}
else {
decisionHandler(.cancel)
}
}

Restricting the domain/url of a WKWebView

I'm trying to include an online form in my application using a UIWebView, and I noticed that once the user finishes the form, s/he can navigate to different addresses. Is there any way I can restrict the domain/url access of a webkit?
(This used to be possible using UIWebView example: https://stackoverflow.com/questions/7673116/restrict-uiwebview-to-certain-pages‌ but it's now deprecated)
WKWebView can utilize the WKNavigationDelegate to restrict navigation.
func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
if let url = navigationAction.request.URL {
if url == permittedUrl {
decisionHandler(.allow)
} else {
decisionHandler(.cancel)
}
}
}

Resources