how do i call objective c code from javascript - ios

i've some javascript code on the webpage in the uiwebview that i want to use to call one of my objective c methods.
i found some code online which i decided to use. but it still doesn't seem to be working. can anyone see where the problem is?
javascript code:
function someMethod() {
window.location = "ios:webToNativeCall";
}
objective c code:
-(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
{
//my code here
}
i'm not sure, how to use this method so it might be that i have implemented it incorrectly.
does anyone have any ideas about what could be causing this?
Thanks in advanced.

This code looks ok, please check whether delegate for UIWebView is set or not.
Otherwise you can use EasyJSWebView download it from Github, it is easy to use.

You must have missed to link the delegate.
Either connect the delegate of the webView to the file owner in the .xib file
or
Use Following code
webView = [[UIWebView alloc] init];
webView.delegate = self;
in your viewDidLoad also write below code
[webView stringByEvaluatingJavaScriptFromString:#"yourJavascriptFunction()"];
Hope it helps you...

Related

Can a UIWebView interact (communicate) with the app?

I went to use UIWebView to display dynamic content, instead of doing it natively using UI-elements. Is it possible to trigger native app functions from simply hitting links inside the UIWebView? Example: hitting a link which then switches current View?
Yes, it's possible. In your html, you write a JS to load a URL with a fake scheme such as
window.location = "request_for_action://anything/that/is/a/valid/url/can/go/here";
Then, in your iOS code, assign a delegate to your webView, and in your delegate, handle
webView:shouldLoadWithRequest:navigationType
with something like
if( [request.URL.scheme isEqualToString: #"request_for_action"] )
{
// parse your custom URL to extract parameter, use URL parts or query string as you like
return NO; // return NO, so webView won't actually try to load this fake request
}
--
Just an aside, you can do the other way, let iOS code invoke some JS codes in your html by
using
NSString* returnValue = [self.webView stringByEvaluatingJavaScriptFromString: "someJSFunction()"];
Yes! When the user presses a link, you hear about it in the web view's delegate and can then do whatever you want. Powerful stuff can be done this way.
The web view's delegate is sent webView:shouldStartLoadWithRequest:navigationType:. You analyze what happened, and respond as you wish. To prevent the web view from trying to follow the link (which may be completely fake, after all), just return NO.
In this example from the TidBITS News app, I have a link in the Web page that uses a totally made-up play: scheme. I detect that in the delegate and play:
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)r
navigationType:(UIWebViewNavigationType)nt {
if ([r.URL.scheme isEqualToString: #"play"]) {
[self doPlay:nil];
return NO;
}
if (nt == UIWebViewNavigationTypeLinkClicked) {
[[UIApplication sharedApplication] openURL:r.URL];
return NO;
}
return YES;
}
Implement the UIWebViewDelegate method webView:shouldStartLoadWithRequest:navigationType:.
Handle navigationType and the request as needed.

iOS webViewDidFinishLoading not being called

I have a UIWebView and want to display an activity indicator while it is loading. And then hide it when the webViewDidFinishLoading. The only problem is that I am getting this NSURLErrorDomain error -999 thing going on. After searching around I found this fix which works to not display any error message but my webViewDidFinishLoading doesn't ever get called to get rid of my activity indicator and other stuff that I have going on. I guess I could just make a call to the didFinishLoading method in my webViewDidFailWithError method if it fails with -999 but that seems super hacky and wrong. Any ideas on how to fix this?
edit*
I have figured out where the webview was being asked to load twice so I was able to get rid of the error -999. However, it seems neither of the delegate methods are being called unless I try to load the webview twice (in which case the webViewDidFinishLoading method is only called once).
- (void)viewDidLoad
{
self.webView.delegate = self;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refresh)
name:#"DidBecomeActive"
object:nil];
[super viewDidLoad];
}
-(void)refresh{
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://myapp.com/app/"]]];
self.webView.scrollView.bounces = NO;
}
- (void)webViewDidFinishLoading:(UIWebView *)wv
{
NSLog(#"finished loading");
[self.activityInd stopAnimating];
[self.view bringSubviewToFront:wv];
}
- (void)webView:(UIWebView *)wv didFailLoadWithError:(NSError *)error
{
NSLog(#"Failed: %#", error);
if([error code] == NSURLErrorCancelled){
return;
}
[self.activityInd stopAnimating];
[[[UIAlertView alloc] initWithTitle:#"Can't find server" message:#"Check your internet connection and try again." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil]show];
}
Did u assigned the UIWebView delegates to its object like the following
webViewObject.delegate = self
Copy/Paste error.
- (void)webViewDidFinishLoading:(UIWebView *)wv
Should be changed to:
- (void)webViewDidFinishLoad:(UIWebView *)wv
implemente the protocol "UIWebViewDelegate" in .h file
In case you ended up here because you're wondering why your delegate methods aren't being called when the bug wasn't due to an incorrectly written delegate method:
Say your webview is normally instantiated via Interface Builder, but you forget to hook it up correctly (meaning it isn't instantiated). You can still set its delegate (e.g., self.webview.delegate = self;) without crashing or exceptions (provided self conforms to the UIWebViewDelegate protocol).
Similarly, you can load HTML into it (e.g., [self.webview loadHTMLString:someHTMLString baseURL:nil];) and the app will continue along happily without complaints. This would take you to an awkward situation where you've set the delegate, written the delegate methods correctly, loaded something into the webview, but your delegate methods will never fire.
So the advice for that situation: make sure you double check that your webview is connected properly (to the correct instance property/variable) in Interface Builder.

Disable UIWebView hyperlinks

My goal is to allow UIWebView load initial link, but disallow any further navigation.
I saw question:
Disable hyperlinks in UIWebView
So, I wired referenced webView property from interface builder.
I specified that my UIViewController uses UIWebViewDelegate:
#interface LegalViewController : UIViewController<UIWebViewDelegate>
In the code, on viewDidLoad, I do following:
mFirstLoad = TRUE;
webView.delegate = self;
And I have following code:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if (!mFirstLoad)
return FALSE;
mFirstLoad = FALSE;
return TRUE;
}
shouldStartLoadWithRequest is called both initial call and when I click on the link. However, even if shouldStartLoadWithRequest returns FALSE, UIWebView still proceeds and loads a new page.
I see this problem on iOS Simulator 6.0
How can I fix this behavior?
return NO based on type to exclude links
return !(navigationTpe==UIWebViewNavigationTypeLinkClicked);
Is it possible your boolean is getting reset somehow? What happens if you just return NO for (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType?
Here is the same thing which I wrote in comments:
I think I found the reason for the problem. I am not sure how to properly call it (not a big expert on HTML and Javascript). However the link has following code : "<a href="/something" data-transition="flip"</a> As result, callback is called, but it looks like results of this callback is ignored.
As result most likely solution is here: Remove hyperlinks in uiwebview

Why does my WebView not load the new content?

I have a method that loads the content in my WebView:
-(void)loadContent:(NSURLRequest *)requestObj{
//Load the request in the UIWebView.
[webView loadRequest:requestObj];
webView.delegate = self;
NSLog(#"LOAD WEBSITE!!!");
}
when I first call it like this:
[self loadContent:requestObj];
it works fine! But when I call it again for a new URL, it does not work.
I have readed that it will help to call the following before loading the new URL:
[webView stringByEvaluatingJavaScriptFromString:#"document.open();document.close()"];
But it doesn't change the result. Does anyone know how to handle this? Please be patient with me, I'm new in the iOS-world.
Ok i find out, my WebView is Null, but why? I call it from the ViewController and it has to be there. Does someone know how to handle this?
UPDATE: It is not Null any more cause i do this:
if(!webView)
{
webView = [[UIWebView alloc]init];
}
But it does not change the content when i do this: [webView loadRequest:requestObj];
try reloading the view like self reload.nameOfTheView
Is your webview created in a nib? If so, it may not be connected.
http://sweng.epfl.ch/tutorials/getting-started-with-ios-developement-xcode-and-objective-c
you can go through the above link and find a step by step procedure
http://www.raywenderlich.com/2712/using-properties-in-objective-c-tutorial
you can download a sample code from the above link.

How To Clear A UIWebView

I am very new to the whole programming business, and was wondering if there is any way to clear the contents of a UIWebView in iphone programming, so that the loading symbol for the next view is not showing up in front of the last view.
Many Thanks,
Thomas
Try setting the URL to about:blank and reload the page.
Just load an empty html string into it
[self.webView loadHTMLString:#"" baseURL:nil];
Answer extension for documentation purposes to maybe help someone else:
I had the same desire (clear content before loading next url) but had a UIWebView delegate set to receive webviewDidFinishLoad:(UIWebView)webview message and update another part of UI in response.
Problem: the call to clear the content to also called delegate method, so getting false-hits (that is, getting call when clear is done, too, but delegate is coded to expect call only when real content is loaded).
Solution: use a known URL for clear, and have webviewDidFinishLoad: ignore calls made when that URL is finished:
- (void) startLoadOfNextURL:(NSURL*)url
{
// clear:
[self.webView loadHTMLString:#"" baseURL:nil];
// Load real next URL
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSLog(#"WebView finished loading: %#", webView);
if ([self.webView.request.URL.absoluteString isEqualToString:#"about:blank"]) {
NSLog(#" This is Blank. Ignoring as false event.");
}
else {
NSLog(#" This is a real url");
[self updateUIInSomeWay];
}
}
Note: using this:
[self.webView loadHTMLString:#"about:blank" baseURL:nil];
actually causes the words "about:blank" to appear as text in the webview's content pane!
Final complication: In practice, with my two [webview load...] calls so close together, I was finding that instead of a "loaded" event for the clear, the webview was actually canceling it in favor of the second request and calling webView: didFailLoadWithError: for the first load request. Thus, I had to put similar code in that event:
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
NSLog(#"WebView error on: %#", webView);
NSLog(#"Error is: %#", error);
NSURL* failingURL = [error.userInfo objectForKey:#"NSErrorFailingURLKey"];
if ([failingURL.absoluteString isEqualToString:#"about:blank"]) {
NSLog(#" This is Blank. Ignoring.");
}
else {
NSLog(#" This is a real URL.");
[self doSomethingAboutError];
}
}
Swift, Xcode 7 beta 5
webView.loadRequest(NSURLRequest(URL: NSURL(string: "about:blank")!))
Swift 4.0 , XCODE 9
webView.loadRequest(URLRequest.init(url: URL.init(string: "about:blank")!))
Same answer in Swift 4.2, xCode 10
if let clearURL = URL(string: "about:blank") {
myWebView.loadRequest(URLRequest(url: clearURL))
}

Resources