webViewDidFinishLoad not calling when having javascript content in webpage - javascript

I'm using UIWebView in a project. Sometimes it doesn't call the webViewDidFinishLoad method. Because the web page have some javascripts. The method
- (BOOL) webView: (UIWebView *) webView shouldStartLoadWithRequest: (NSURLRequest *) request navigationType: (UIWebViewNavigationType) navigationType
is getting call but webViewDidFinishLoad doesn't. I want to catch that method. Because I'm start an animation when the webview start loading. Then I want to stop this animation when it finished. It's not working with websites having javascript content. Any one have an idea please?
Thanks

webViewDidFinishLoad method gets called when the UIWebView has finished loading the url, in your case since you are calling a javascript, it doesn't load your content, it just calls a javascript function in your already loaded webview. But YES you can catch the javascript actions in the same method you stated as below
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSString *url = [[request URL] absoluteString];
if(navigationType == UIWebViewNavigationTypeLinkClicked){
if([url rangeOfString:#"SOMETHING"].length > 0 ){
//if your action returns something appended in your url like the anchors work
//DO YOUR STUFFS
}
}
return TRUE;
}

apparently, the webview in ios checks specifically for "iframe" tags in the html's dom and in case it finds, it creates events based on that tag as well. therefore, a simple however a patchy solution would be adding the following code in the part of the dom that is changing (for example, in the actual template of each section):
<iframe></iframe>
did the trick for me..

Related

I would like to export the contents of ios web view as html

I am writing an app for ios to extract information from a webpage, however, the relevant pieces on the page are built by javascript. So when it is loaded by webview, the javascript is executed and the information displays no problem. If I try to load the page into a string by using the following method, the javascript is loaded, but not actually executed, therefore the string has no useful data in it.
NSData *urlData = [NSData dataWithContentsOfURL:[NSURL URLWithString:fullURL]];
NSString *responseString = [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];
Is there another way besides loading the page into webview and exporting it from there? If not, how do you do that?
I'm not sure if there's another way outside of letting the UIWebView execute the JS and render the page, but if you do end up going this route, you could just grab the HTML of the whole page and pass that to the native end like so:
[dummyWebView stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('html')[0].outerHTML;"];
Listening to the window.load event might be better to know when the page has finished going through all the JS
Good luck!
You set delegate to webView: self.webView.delegate = self; and implement UIWebViewDelegate:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *html = [webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.outerHTML"];
NSLog(#"html1 = %#", html);
// or use
NSString *html2 = [webView stringByEvaluatingJavaScriptFromString:#"document.body.innerHTML"];
NSLog(#"html2 = %#", html2);
}

User Interaction Enabled Javascript

I am writing a Javascript application and am going to wrap it in a native iOS application. I would like to block user interaction on the UIWebView containing the JS app for a second or two following an event.
Normally I would use the self.webView.userinteractionenabled = NO but the event is triggered in Javascript. How can I block the user from interacting with the web view?
Guessing return false on a touch event of some sort? It's scrolling that I want to block.
Thanks!
When the event occurs in your Javascript code you can send a message to the native wrapper by using the following method:
Set up the following UIWebViewDelegate method (don't forget to set the delegate for the UIWebView):
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = [request URL];
if ([[url scheme] isEqualToString:#"block"]) {
// do the your blocking code here
return NO;
}
return YES;
}
Now when your event happens, call the delegate method from your javascript code:
window.location.href = "block://";

Close UIWebView using javascript:window.close();

The question sounds weird, but here is my case.
I have a UIWebView in my UIView ( done by [self.view addSubview:webView]; ) which occupies full screen. It intentionally hides the UIView before the UIWebView clicks on an action javascript:window.close();.
How do I associate JavaScript in UIWebView page to UIView's action , e.g. [webView removeFromSuperView]; ?
This is possible:
Set the location to something with your own scheme in the url, i.e.
document.location.href = "myscheme://DoSomething"
This will cause the UIWebViewDelegate method shouldStartLoadWithRequest: to be called with an NSURLRequest parameter whose scheme is"myscheme". So you look for this scheme and extract the DoSomething and then act on the DoSomething, which in your case would be to call remove from superView.
(In the UIWebView dealloc probably need to make sure you call stopLoading)

How to received alert() action from javascript into Cocoa application via WebView

I was develop some Cocoa application with WebView. Now I can evaluate javascript to HTML file by using evaluateWebScript:
But I need to receive an alert() event from javascript to display in Cocoa's NSAlertSheet.
How to do with cocoa development ?
You need to set an object as the WebUIDelegate of the WebView (using the setUIDelegate: method) and in that object implement the ‑webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame: delegate method. This method will be called when a page loaded into the WebView calls the alert() JavaScript function.
In your implementation of the delegate method, you should display an alert. The alert should:
display the exact message string that is passed in to the method
indicate that the message comes from JavaScript
contain only one button, an OK button
Here is a basic example:
- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message
{
NSAlert* jsAlert = [NSAlert alertWithMessageText:#"JavaScript"
defaultButton:#"OK"
alternateButton:nil
otherButton:nil
informativeTextWithFormat:#"%#", message];
[jsAlert beginSheetModalForWindow:sender.window modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
}
You can try to override JavaScript alert function on window. In your custom alert you can redirect to predefined url, e.g. app://alert/something%32is%32wrong. That kind of redirect can be handled by UIWebView through webView:shouldLoadRequest:.
PS: I didn't try it :)

How to determine iFrame finished loading in UIWebView

In my app, I need a way to tell when my webview is finished loading. It is very easy to do that if content is html. However, my content source is javascript with iFrame inside, it will cause UIWebView finishedLoad method called several times. Is there anyway I can check to see if the iframe is finished loading?
The only foolproof method I've found is to listen to the three methods that say it's about to start loading, and that it finished loading (plus equivalent for "failed"), and to manually maintain a count for each.
i.e. something like:
int outstandingRequests;
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
outstandingRequests++;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
outstandingRequests--;
if( outstandingRequests < 1 )
viewLoadingPleaseWait.hidden = TRUE;
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
outstandingRequests--;
}
I've also usually had to overrid the didFail method - Apple incorrectly uses this to report that e.g. the YouTube player has taken over the handling of a YouTube video. It's NOT a fail, it's a "page was loaded by a different application".
e.g.
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
outstandingRequests--;
if( [error code] == NSURLErrorCancelled )
{
NSLog(#"[%#] ...webView CANCELLED loading", [self class] );
}
else if( [[error domain] isEqualToString:#"WebKitErrorDomain"]
&& [error code] == 204)
{
// no worries ... YouTube, iCal, or etc took over the page load
}
}
(If it is the same domain) you can call a function (in the parent) from the iframe.
top.iFrameLoaded();
To tell if a webview is loading, you can use
webView.isLoading
to check if all the frames of a webview are done loading. No counting the number of iframes necessary. Simply check if isLoading is true inside webViewDidFinishLoad:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIWebView_Class/Reference/Reference.html

Categories

Resources