I have a WebView which is loading and HTML String and I want it to catch clicks on links.
For that I need to use the webView:shouldStartLoadWithRequest:navigationType method.
The problem is that this method gets called multiple times before the HTML content is fully loaded and I only want to start catching clicks at that moment.
The question is how to know when the HTML content is fully loaded ? I thought it was simple so I created a boolean as an iVar of the ViewController containing the WebView and I set it to YES after calling loadHTMLString. Then, in webView:shouldStartLoadWithRequest:navigationType I was testing if that boolean was true and if it was the case I was outputting something like "OK". But "OK" was appearing without clicking on a link => fail.
Any idea on how I could make this work ?
Thanks in advance
You could use the webViewDidFinishLoad: delegate method to know when the HTML is loaded.
But I'd rather use another solution:
In webView:shouldStartLoadWithRequest:navigationType: you can filter requests by navigation type:
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
// Catch links
return NO; // if you want to cancel the request, else YES
}
- (void)webViewDidFinishLoad:(UIWebView *)webViews{
}
this method will callwhen the HTML content is fully loaded.
it may helps you.
Related
I am loading a "webpage1" on an uiwebview and saving its first request on an instance variable "webviewHistory". Then, I must reuse that webview to load another page, "webpage2" (saved its first request to "webviewHistory" too), and history should start now from this request. Problem is if I execute goBack (button IBAction) from "webpage2", I can keep going back to "webpage1" history and following.
If I check request and compare with initial saved, works! but not with redirections, for example, if I trigger request to www.youtube.com, request is redirectioned to m.youtube.com and first one is not saved as navigation history! how to solve it?
if (![webViewSocial.request.URL.absoluteString isEqualToString:self.webviewHistory]){
[webViewSocial goBack];
}
UIWebviews have instance methods that allow you to go backwards and forwards with the history, without you having to track the last request. Is there a particular reason you are saving the last request specifically?
Sample code:
if ([webView canGoBack]) {
[webView goBack];
}
Here is a project that is a simple uiwebview browser if you want to play with it:
https://github.com/msencenb/UIWebView-Example
for swift 3 version of Msencenb answer:
if webView.canGoBack {
webView.goBack()
}
I am loading a html page using loadHTMLString.
[myWebview loadHTMLString:myHtmlStr baseURL:nil];
Its loading properly. In this html web page, i'm also adding buttons, drop down(with selection) etc. I want to catch the action events in my code now for these web page controls. For example, from the drop down if user chooses an option, i need to add another 'textarea' dynamically in the same web page. and, if user clicks on a button(button from the webview), i need to handle some events. I would like to know, how to do some tasks under the events triggered for controls in web view which is generated by my string.
Could someone please advise me.
to handle event on button in webview load a url in webview for ex:http://button1clicked and then in webView:shouldStartLoadWithRequest:navigationType: method check if the url is button1clicked then return no and also perform your action which you want to do on button clicked.
for example:
write this in webView:shouldStartLoadWithRequest:navigationType: method.
if([[[request URL] absoluteString] isEqualToString:#"http://button1clicked"])
{
//perform you action you want to do
return NO;
}
and on button click call javascript function window.location='http://button1clicked';
The documentation clearly states that UIWebView is not intended for Sub-Classing. However, you can still detect all the events.
But maybe this will help : Tutorial
I have a form in the UIWebView to interact with a web service, when I submit the form, the data gets sent to a web service and it will return the result to another UIWebView. The two UIWebViews are under a navigation controller, so when the use submits the form, it slides to another view to display the result. Can anyone point me out how I can achieve this? What do I fill in the "action" attribute in the form element? How can I get the user input back to the application so I can use the web service? I am new to this field, any help will be appreciated. Thanks!
Update:
Is there a way to save form data from web view back to my program? I think it's better to save form data back to the program (i.e. store params into nsstring) when I click submit button, and then start querying web service.
You can use the
stringByEvaluatingJavaScriptFromString
function for firing a javascript method from objective c and get a return value from that method.
For example
//Calling the getTheUsername in the javascript.
NSString *userName = [yourWebView stringByEvaluatingJavaScriptFromString:#"getTheUsername()"];
and in javascript
//Method in javascript
function getTheUsername()
{
return userNameVariable;
}
And I doubt that here you may wanna do vice-versa (Call obj-c method from javascript). This cannot be done directly here is the work around.
Set a UIWebViewDelegate, and implement the method webView:shouldStartLoadWithRequest:navigationType:. In your JavaScript code, navigate to some fake URL that encodes the information you want to pass to your app, like, say:
window.location = "someLink://yourApp/form_Submitted:param1:param2:param3";
In your delegate method, look for these fake URLs, extract the information you need, take whatever action is appropriate, and return NO to cancel the navigation.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSLog(#"%#",[[request URL] query]);
return YES;
}
If I understood your problem correctly, I think following steps will help you to provide the solution.
In the action of form, you need to write the URL to the web service.
In your form, the name of the input field should be matched with the name of the parameters expected for the web service.
In your first UIWebView Navigation control, Create the object of screen having second UIWebView and set the response of the web service to the instance member of the object.
In your first UIWebView Navigation control, you need to write
[self presentModalViewController:webView2Object animated:YES];
In the screen of having webView2, parse the response before loading the second UIWebView. and inject it with the displayed page using javascript.
Yes, I know UIWebView has didFinishedLoad & didStartLoad delegate.
However, the didFinishedLoad does not mean the full completion. It may be called when one of the items that the UIWebView is finished loading. i.e., UIWebView may call this delegate several times while loading a single page.
So anyway can tell me how to check whether the UIWebView is fully loaded?
Thanks
J
I have poor experience with DOM but after some searching I found that the document.readyState is the great option.
From w3schools:
Definition and Usage
The readyState property returns the (loading) status of the current document.
This property returns one of four values:
uninitialized - Has not started loading yet
loading - Is loading
interactive - Has loaded enough and the user can interact with it
complete - Fully loaded
So I'm using this to know when UIWebView has loaded the document:
- (void)readyState:(NSString *)str
{ NSLog(#"str:%#",str);
if ([str isEqualToString:#"complete"]||[str isEqualToString:#"interactive"]) {
NSLog(#"IT HAS BEEN DONE");
[pageLoadingActivityIndicator stopAnimating];
}
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//other code...
[self readyState:[browserWebView stringByEvaluatingJavaScriptFromString:#"document.readyState"]];
}
http://www.codingventures.com/2008/12/using-uiwebview-to-render-svg-files/
on Javascript communicating back with Objective-C code
Maybe use document location hash.
And add in the webview html body:
<body onload="document.location.hash='myapp:myobject:myfunction';">
I know its a little bit hacky but works. And it can be used in ajax based contents, because its up to you when you want to call your ready method. Or it can be used as a complete communication scheme.
What you can do is, display a network indicator on the view which is visible in the status bar. When your page is being loaded the indicator will continue rotating until and unless the page is completly loaded. When the page completely loads, the indicator will stop rotating and will be invisible.
Just have a look at this example : Network indicator
I have basic web browser implemented using a UIWebView. I've noticed that for some pages, none of the UIWebViewDelegate methods are called.
An example page in which this happens is: http://www.youtube.com/user/google. Here are the steps to reproduce the issue (make sure you insert NSLog calls in your controller's UIWebViewDelegate methods):
Load the above youtube URL into the UIWebView
[notice that here, the UIWebViewDelegate methods do get called when the page loads]
Touch the "Uploads" category on the page
Touch any video in that category
[issue: notice that a new page is loaded, but none of the UIWebView delegates are called]
I know that this is not an issue of UIWebView's delegate not being set properly, since the delegate methods do get invoked when loading other links (e.g. if you try clicking on a link that takes you outside of youtube, you'll notice the delegate methods getting called).
My gut feeling initially was that it might be because the page is loaded using AJAX, which may not invoke the delegate method. But then when I checked the iPhone's Safari, it did not exhibit this problem, so it must be something on my side.
I've also noticed that Three20's TTWebController has the exact same issue as I'm having.
But the problem that arises from this issue is that without the delegate methods called, I'm unable to update the UI to enable/disable the back and forward browsing buttons when new requests are loaded.
And idea why this is happening or how can I work around it to update the UI when a new request is made?
This isn't an iOS bug - the page isn't actually reloading. The UIWebView delegates are triggered following new page requests, but that page doesn't do that.
Look very carefully at what happens in desktop Safari when you click the video link on that page as you describe. Make sure you pay attention to the address bar. The address will change, but critically the page will not reload.
This is all handled by JavaScript, not by reloading the page. Simply put, the page never reloads, so there's no reason for the UIWebView delegates to be called.
If you don't believe me, to conclusively prove this try repeating the steps you describe with JavaScript disabled. You'll notice the page behaves completely differently.
this is not good solution but im using NSTimer for updating status of buttons:
- (BOOL)webView:(UIWebView *)_webview shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (!_timer && [request.URL.absoluteString rangeOfString:#"youtube.com"].length != 0) {
_timer = [NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:#selector(checkNavigationStatus)
userInfo:nil
repeats:YES];
}
return YES;
}
//....
//....
//....
- (void)checkNavigationStatus
{
// Check if we can go forward or back
backButton.enabled = self.webView.canGoBack;
forwardButton.enabled = self.webView.canGoForward;
}
Looks like this got fixed in iOS 4.2. It works in iOS 4.2.