WKWebView ignores onclick javascript - javascript

Currently I have a WebView which I render using WKWebView and Swift. I have added all the delegates but none of them is getting called. Am I handling it incorrectly ? I did add WKScriptMessageHandler too but none of them is triggering the onlick javascript call.
My swift code is below:
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
print("here - \(message)");
}
func webView(webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: () -> Void) {
print("here - \(message)");
}
func webView(webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: (String?) -> Void) {
print("here - \(prompt)");
}
func webView(webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: (Bool) -> Void) {
let alert = UIAlertController(title: "", message: message, preferredStyle: UIAlertControllerStyle.Alert);
alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: UIAlertActionStyle.Default, handler: { (UIAlertAction ) -> Void in
completionHandler(false);
}));
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: { (UIAlertAction ) -> Void in
UIApplication.sharedApplication().openURL(NSURL(string: (frame.request.URL?.host)!)!);
completionHandler(true);
}));
self.presentViewController(alert, animated: true, completion: nil);
}
func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {}
And javascript code:
Agree
UPDATED: The following code worked for me....
func webView(webView: WKWebView, createWebViewWithConfiguration configuration: WKWebViewConfiguration, forNavigationAction navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView?

Related

WKUserContentController isn't called when Javascript calls handler

I'm developing IOS App using Webkit, Swift.
And I wanna close view controller which shows webkit when my webview logic is done. Using WKUserContentController, I implemented logic.
But It didn't work.
Below is my code.
This is Swift.
import UIKit
import WebKit
class SelfAuthVC: UIViewController, WKNavigationDelegate, WKUIDelegate, WKScriptMessageHandler {
private var webView: WKWebView!
let contentController = WKUserContentController()
let config = WKWebViewConfiguration()
override func viewWillAppear(_ animated: Bool) {
contentController.add(self as WKScriptMessageHandler, name: "callbackHandler")
config.userContentController = contentController
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
config.preferences = preferences
webView = WKWebView(frame: view.bounds, configuration: config)
view.addSubview(webView)
let url = Bundle.main.url(forResource: "auth", withExtension: "html")!
webView.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url)
webView.load(request)
webView.navigationDelegate = self
webView.uiDelegate = self
}
override func viewDidLoad() {
super.viewDidLoad()
}
func webViewDidClose(_ webView: WKWebView) {
self.navigationController?.popViewController(animated: true)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("var my_email = '\(UserInfo.shared().email!)'") { (result, error) in
guard error == nil else {
print(error)
return
}
}
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print("didReceive message here")
if(message.name == "callbackHandler"){
print("callbackHandler: \(message.body)")
self.dismiss(animated: true, completion: nil)
self.navigationController?.popViewController(animated: true)
}
}
}
Below is JS
<body>
<script language="JavaScript">
IMP.certification({
min_age: 18
}, function(rsp) {
if ( rsp.success ) {
$.ajax({
method : "POST",
url : "https://******/user/iamport",
dataType : 'json',
data : {
imp_uid : rsp.imp_uid,
user_email: my_email
}
}).done(function(rsp) {
// 이후 Business Logic 처리하시면 됩니다.
(function finish(){
window.webkit.messageHandlers.callbackHandler.postMessage("trigger from JS");
try {
webkit.messageHandlers.callbackHandler.postMessage(
'done'
);
} catch(err) {
console.log('The native context does not exist yet');
}
}())
});
} else {
// Auth failed
var msg = '인증에 실패하였습니다. 관리자에게 문의하세요';
msg += '에러내용 : ' + rsp.error_msg;
alert(msg);
}
});
</script>
</body>
I think I wrote codes that is needed.
But after authorization process, ViewContoller don't disappear.
What changes are needed to solve this problem?
I forgot to add this codes.
config.userContentController = contentController
contentController.add(self, name: "authAction")

Catch events javascript in swift

In android i use this
https://developer.android.com/reference/android/webkit/JavascriptInterface
to catch the events javascript in java
but in swift, what can i use ?
i just found to execute javascript for swift, but i want catch a click event.
Example, when the user click in button, change the screen according the option selected.
You can use WKWebView for this
let contentController = WKUserContentController()
contentController.add(self, name: scriptMessageName)
let config = WKWebViewConfiguration()
config.userContentController = contentController
let webView = WKWebView(frame: self.view.frame, configuration: config)
Then confirm you ViewController to WKScriptMessageHandler, WKNavigationDelegate
extension ViewController: WKScriptMessageHandler, WKNavigationDelegate {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
switch message.name {
case scriptMessageName:
someAction()
default:
break
}
}
}

WKWebView popup not showing up

I've been working on a simple app that makes a webview of a website where students can take exams.
So basically the problem I have is that when students are done, they have to click on a button that will send the answers.
A popup will appear to make them confirm.
https://i.stack.imgur.com/5GhB8.png
Except that it doesn't show up. Nothing happens when the button is pushed.
It works flawlessly on Safari and I've noticed that it works on the deprecated webview (UIWebview) but I've been trying to make it work on WKWebView.
I'm definitely no swift expert so I apologize if the answer is easy. I've been trying to find some answers about my problem but I'm not sure how to implement it.
Thank you in advance for any help,
import UIKit
import WebKit
class webViewController: UIViewController {
#IBOutlet weak var webview: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let lien = "***"
if let url = URL(string: lien) {
let request = URLRequest(url: url)
_ = webview.load(request);
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I also faced similar issue, mine was popup for connecting facebook won't show in WKWebView but works fine on safari browser.
This code was causing the issue.
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
//This condition was causing the problem while trying to get popup
if (!navigationAction.targetFrame.isMainFrame) {
[webView loadRequest:navigationAction.request];
}
return nil;
}
I changed it to following code and it worked
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
if (navigationAction.targetFrame == nil) {
NSURL *tempURL = navigationAction.request.URL;
NSURLComponents *URLComponents = [[NSURLComponents alloc] init];
URLComponents.scheme = [tempURL scheme];
URLComponents.host = [tempURL host];
URLComponents.path = [tempURL path];
if ([URLComponents.URL.absoluteString isEqualToString:#"https://example.com/Account/ExternalLogin"]) {
WKWebView *webViewtemp = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
webViewtemp.UIDelegate = self;
webViewtemp.navigationDelegate = self;
[self.view addSubview:webViewtemp];
return webViewtemp;
} else {
[webView loadRequest:navigationAction.request];
}
}
return nil;
}
Swift version:
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if navigationAction.targetFrame == nil {
let tempURL = navigationAction.request.url
var components = URLComponents()
components.scheme = tempURL?.scheme
components.host = tempURL?.host
components.path = (tempURL?.path)!
if components.url?.absoluteString == "https://example.com/Account/ExternalLogin" {
let webViewtemp = WKWebView(frame: self.view.bounds, configuration: configuration)
webViewtemp.uiDelegate = self
webViewtemp.navigationDelegate = self
self.view.addSubview(webViewtemp)
return webViewtemp
} else {
webView.load(navigationAction.request)
}
}
return nil
}
Hope this helps you
My solution was implementing the WKUIDelegate and adding the functions for the different scenarios (alerts) that the web view may present:
extension WKWebViewController: WKUIDelegate {
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: #escaping () -> Void) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "OK button"), style: .default, handler: { (action) in
completionHandler()
}))
present(alertController, animated: true, completion: nil)
}
func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: #escaping (Bool) -> Void) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "OK button"), style: .default, handler: { (action) in
completionHandler(true)
}))
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "Cancel button"), style: .default, handler: { (action) in
completionHandler(false)
}))
present(alertController, animated: true, completion: nil)
}
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: #escaping (String?) -> Void) {
let alertController = UIAlertController(title: nil, message: prompt, preferredStyle: .actionSheet)
alertController.addTextField { (textField) in
textField.text = defaultText
}
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "OK button"), style: .default, handler: { (action) in
if let text = alertController.textFields?.first?.text {
completionHandler(text)
} else {
completionHandler(defaultText)
}
}))
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "Cancel button"), style: .default, handler: { (action) in
completionHandler(nil)
}))
present(alertController, animated: true, completion: nil)
}
}
When web view demands the new popup window than UIDelegate of WKWebView will come in picture.
Follow these steps to show POP-Up view in WKWebView
Take a another web-view
private var popupWebView: WKWebView?
Assign the uiDelegate of your main web-view to self
webView?.uiDelegate = self
Confirm the WKUIDelegate of to your controller
extension PaisaPalVC: WKUIDelegate {
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
popupWebView = WKWebView(frame: view.bounds, configuration: configuration)
popupWebView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
popupWebView?.navigationDelegate = self
popupWebView?.uiDelegate = self
if let newWebview = popupWebView {
view.addSubview(newWebview)
}
return popupWebView ?? nil
}
func webViewDidClose(_ webView: WKWebView) {
webView.removeFromSuperview()
popupWebView = nil
}
}
Hope this helps you😊
I tried the other way round and it worked for me. Here is the code:
Create a instance of WebView
fileprivate var webView: WKWebView?
Initialize instance and make assign it to view.
override func loadView() {
webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
webView?.uiDelegate = self
webView?.navigationDelegate = self
view = webView
}
Thereafter, just add the following delegate method:
func webView(_: WKWebView, createWebViewWith _: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures _: WKWindowFeatures) -> WKWebView? {
self.webView?.load(navigationAction.request)
return nil
}
Voila! Everything will work same as UIWebView.
Note: You won't be able to tap few links on the WebSite, because they would be HTTP instead of HTTPS. WKWebView by default blocks all HTTP requests which aren't secure.
To bypass, just add NSExceptionAllowsInsecureHTTPLoads as true in info.plist file.

How to return boolean to javascript function from swift using wkwebview

This is my function in android :
#JavascriptInterface
public boolean GetMobileVersion() {
return true;
}
This is Calling function in JavaScript :
$(window).load(function () {
IsCallByMobileApp = false;
try {
IsCallByMobileApp = app.GetMobileVersion();/*Is call by android app*/
} catch (e) {
IsCallByMobileApp = false;
}
}
In iOS I am try to achieve same approach using WKWebView like this but it's not working:
func userContentController(_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage) {
if(message.name == callbackhandler) {
webView.evaluateJavaScript("GetMobileVersion();") { (true, error) in
guard error == nil else {
print("there was an error")
return
}
print(Bool(true))
}
}
}
Can anyone tell me How to send true to Javascript function? Please give me answer in detail because I am new to iOS and Swift.
I have created a GitHub project for this. https://github.com/BKRApps/WKWebView-JS. check it out for more details.
Update the JavaScript:
function getMobileVersion(){
webkit.messageHandlers.VersionHandler.postMessage({})
}
function receivedMobileVersion(mobileVersion){
//here you will be getting the mobile version. Then execute the logic.
// i have added this only to cross check the version. you don't need to add this.
if(mobileVersion === true) {
webkit.messageHandlers.VerifyHandler.postMessage({version:mobileVersion})
}
}
getMobileVersion()
Add the below code to WKWebView Configuration:
configuration.userContentController.add(self, name: "VersionHandler")
// i have added this only to cross check the version. you don't need to add this.
configuration.userContentController.add(self, name: "VerifyHandler")
Update the WKScriptMessageHandler delegate:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
switch message.name {
case "VersionHandler":
let mobileVersion = true //write the version logic and send the true or false.
let sendMobileVersionScript = "receivedMobileVersion(\(mobileVersion))"
self.wkWebView?.evaluateJavaScript("\(sendMobileVersionScript)", completionHandler: { (any, error) in
print("hello")
})
case "VerifyHandler":
print(message.body) // i have added this only to cross check the version. you
default:
break;
}
}
for more info : http://igomobile.de/2017/03/06/wkwebview-return-a-value-from-native-code-to-javascript/
Not sure if with WKWebView is the same as webview but you could try with plaintext as following:
func userContentController(_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage) {
if(message.name == callbackhandler) {
webView.evaluateJavaScript("GetMobileVersion(true);") { (true, error) in
guard error == nil else {
print("there was an error")
return
}
print(Bool(true))
}
}
}

running local html in wkwebview - no javascript

I am trying to get a mobile webpage in an iOS app. Unfortunately the web view is not executing any javascript. After googling a while it turns out that apple restricts local javascript.
Any suggestions how to make it work anyway?
import UIKit
import WebKit
import AVFoundation
class ViewController: UIViewController ,WKUIDelegate, WKNavigationDelegate {
var webView : WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let webView = WKWebView()
let htmlPath = Bundle.main.path(forResource: "Webpage/index", ofType: "html")
let htmlUrl = URL(fileURLWithPath: htmlPath!, isDirectory: false)
webView.loadFileURL(htmlUrl, allowingReadAccessTo: htmlUrl)
webView.navigationDelegate = self
view = webView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
// WKNavigationDelegate
func webView(webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) {
print(error.localizedDescription)
}
func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("Loading")
}
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
print("Loaded")
}

Categories

Resources