Invoke Method in Objective C Code from HTML Code Using Uiwebview

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



Leave a reply



Submit