Invoke method in objective c code from HTML code using UIWebView
To call method of Objective-C in JS:
the below url helps in doing that
How to invoke Objective C method from Javascript and send back data to Javascript in iOS?
There is no way of executing, we make workaround by a navigation to other page and during the navigation, a webview delegate will watch for prefix of the navigation and execute the method we specified.
sample.html
<html>
<head>
<script type='text/javascript'>
function getText()
{
return document.getElementById('txtinput').value;
}
function locationChange()
{
window.location = 'ios:webToNativeCall';
}
</script>
</head>
<body style='overflow-x:hidden;overflow-y:hidden;'>
<h2 style = "font-size:16px;" align='center'>Hi Welcome to Webpage</h2>
<br/>
<p align='center' style = "font-size:12px;">Please Click the button after entering the text</p>
<br/>
<center>
<input type='text' style='width:90px;height:30px;' id='txtinput'/>
</center>
<br/>
<center>
<input type='button' style='width:90px;height:30px;' onclick='locationChange()' value='click me'>
</center>
</body>
</html>
Objective-C code
when you click button in html page the below delegate will fired and navigation cancelled because we return NO and respective method is called
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if ([[[request URL] absoluteString] hasPrefix:@"ios:"]) {
// Call the given selector
[self performSelector:@selector(webToNativeCall)];
// Cancel the location change
return NO;
}
return YES;
}
- (void)webToNativeCall
{
NSString *returnvalue = [self.webviewForHtml stringByEvaluatingJavaScriptFromString:@"getText()"];
self.valueFromBrowser.text = [NSString stringWithFormat:@"From browser : %@", returnvalue ];
}
How to invoke Objective-C method from Javascript and send back data to Javascript in iOS?
There is an API to call JavaScript directly from Objective-C, but you cannot call Objective-C directly from Javascript.
How to tell your Objective-C code to do something from the Javascript in your WebView
You have to serialize your Javascript action into a special URL and intercept that URL in the UIWebView's delegate's shouldStartLoadWithRequest
method.
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType;
There you can deserialize that special URL and interpret it to do what you want on the Objective-C side. (You should return NO
in the above shouldStartLoadWithRequest
method so the UIWebView doesn't use your bogus URL to actually make an HTTP request to load a webpage.)
How to Run Javascript Code from Objective-C
Then you can run Javascript from Objective-C by calling this method on your webview.
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
Example Code
I recommend using a bogus URL scheme so it will be easy to tell the difference between your action URLs and legit requests. You can make this request in the Javascript along these lines:
// JavaScript to send an action to your Objective-C code
var myAppName = 'myfakeappname';
var myActionType = 'myJavascriptActionType';
var myActionParameters = {}; // put extra info into a dict if you need it
// (separating the actionType from parameters makes it easier to parse in ObjC.)
var jsonString = (JSON.stringify(myActionParameters));
var escapedJsonParameters = escape(jsonString);
var url = myAppName + '://' + myActionType + "#" + escapedJsonParameters;
document.location.href = url;
Then in the UIWebView.delegate
's shouldStartLoadWithRequest
method, you can inspect the URL scheme and fragment to check if it's a normal request or one of your special actions. (The fragment of a URL is what comes after the #
.)
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
// these need to match the values defined in your JavaScript
NSString *myAppScheme = @"myfakeappname";
NSString *myActionType = @"myJavascriptActionType";
// ignore legit webview requests so they load normally
if (![request.URL.scheme isEqualToString:myAppScheme]) {
return YES;
}
// get the action from the path
NSString *actionType = request.URL.host;
// deserialize the request JSON
NSString *jsonDictString = [request.URL.fragment stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
// look at the actionType and do whatever you want here
if ([actionType isEqualToString:myActionType]) {
// do something in response to your javascript action
// if you used an action parameters dict, deserialize and inspect it here
}
// make sure to return NO so that your webview doesn't try to load your made-up URL
return NO;
}
(Read this answer if you need help deserializing your json string into an NSDictionary.)
How can I call objective-c code from within an html file in a UIWebView?
You can not have Objective-C code mixed with an HTML file that runs locally on a UIWebView
. That said, there are some workarounds that may fit your needs.
One that I've used, is to have the HTML link to a custom URL, and detect that on the appropriate method in the UIWebView
delegate class, as follows:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
In that method, you would check for the URL
schema you created by means of checking the request
parameter, and then decide what selector to code on your Objective-C code.
How to send events from HTML running inside a UIWebView to native Objective-C code?
I have done this using jQuery and UIWebViewDelegate:
JavaScript (jQuery mobile):
$("#bloodType").change(function() {
url = $("#bloodType option:selected").text();
url = "donordialog:bloodTypeChanged(" + url + ")";
window.location = url;
});
So, the resulting URL looks like: donordialog:bloodTypeChanged(typeAB-)
In my objc code:
-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL *URL = [request URL];
if ([[URL scheme] isEqualToString:@"donordialog"])
{
// now we need to figure out the function part
NSString *functionString = [URL resourceSpecifier];
if ([functionString hasPrefix:@"bloodTypeChanged"])
{
// the blood type has changed, now do something about it.
NSString *parameter = [functionString stringByReplacingOccurrencesOfString:@"bloodTypeChanged" withString:@""];
// remove the '(' and then the ')'
parameter = [parameter stringByReplacingOccurrencesOfString:@"(" withString:@""];
parameter = [parameter stringByReplacingOccurrencesOfString:@")" withString:@""];
// log the paramter, as I don't know what to do with it right now
NSLog(@"%@", parameter);
}
return NO;
}
return YES;
}
This code was copied verbatim from a project I am currently working on, and can verify that this works.
Related Topics
JavaScript and Operator Within Assignment
What Are Alternatives to Document.Write
Merge Two Array of Objects Based on a Key
JavaScript: Object Literal Reference in Own Key'S Function Instead of 'This'
Why Does String to Number Comparison Work in JavaScript
How to Get the Youtube Video Id from a Url
Angularjs Routing Without the Hash '#'
I'Ve Heard Global Variables Are Bad, What Alternative Solution Should I Use
Converting a Js Object to an Array Using Jquery
Whats the Best Way to Update an Object in an Array in Reactjs
How to Highlight Text Using JavaScript
Converting an Object to a String
How to Post a File from a Form With Axios
Evaluating a String as a Mathematical Expression in JavaScript
Check Whether User Has a Chrome Extension Installed
Any Difference Between Await Promise.All() and Multiple Await