UIWebView, determine if page has loaded - iphone

I would like to know when my WebView has finished loading a page. Im quite new to this and I wonder if you have any suggestions. I need to create a "Loading screen" while the page is loading. This is my basic code:
- (void)viewDidLoad {
NSString *urlAddress = #"http://google.se";
//Create a URL object.
NSURL *url = [NSURL URLWithString:urlAddress];
//URL Requst Object
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
//Load the request in the UIWebView.
[webView loadRequest:requestObj];
}
Thanks!

There are two different callbacks when the view finishes loading, successful load and failed load. They are both part of the the UIWebViewDelegate protocol.
Implement it and set yourself as the delegate for your web view. Then implement
- (void)webViewDidFinishLoad:(UIWebView *)webView
to know when the loading has finished, so that you can remove your loading screen, and implement
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
to know if it failed so that you can show and appropriate message to the user instead of an infinite loading screen.

Have a look at the UIWebViewDelegate Protocoll. If you set your delegate, you receive messages like – webViewDidFinishLoad:
that's what you want, isn't it?

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:str]];
}

Related

shouldStartLoadWithRequest doesn't run stringByEvaluatingJavaScriptFromString method

I am trying to run the code below in webview's shouldStartLoadWithRequest delegate method but it doesn't make any changes.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSLog(#"webView shouldStartLoadingWithRequest");
[self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"document.execCommand('bold', false,null)"]];
return TRUE;
}
There is no error, it prints the NSLog and everything in the method works great except "stringByEvaluatingJavaScriptFromString" method.
But if I try to make text bold in another function, for example an IBAction method, works fine.
-(IBAction)boldClick:(id)sender
{
[self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"document.execCommand('bold', false,null)"]];
}
Actually, this is my company's special application and this UIWebView will not show the web pages. I am using it to show some custom HTML pages.
I need to make everything in "shouldStartLoadWithRequest" because I am trying to run an objective-c method from javascript.
UPDATE
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
// Break apart request URL
NSString *requestString = [[request URL] absoluteString];
NSArray *components = [requestString componentsSeparatedByString:#":"];
// Check for your protocol
if ([components count]==3)
{
[self makeBoldText];
return NO;
}
else
{
return TRUE;
}
}
-(void)makeBoldText
{
[self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"document.execCommand('bold', false,null)"]];
}
The doc says that method webView:shouldStartLoadWithRequest: is sent before a web view begins loading a frame. After you return YES in this method, web view starts loading a request. So any javascript you execute will have no effect, because a new page will be loaded after your JS call.
You can probably use webViewDidFinishLoad: method to execute javascript after page finishes to load. Or if you want to trigger JS by clicking on a link, you can use shouldStartLoadWithRequest but return NO from it.

Can I open an URL(a Facebook page) in a FBDialog or something in FBConnect?

I am struggling to find this. Can I open a URL in a FBDialog or using something in FBConnect. I tried to do it like the following. But it doesn't seem to be working.
FBDialog *dlg = [FBDialog new];
[dlg loadURL:#"http://www.facebook.com/pages/Apple-Inc/137947732957611" get:nil];
I don't even know whether this is possible or not. Can you guys please help me?
There are 2 problem to prevent you from your code. First, when you pass a url to -loadURL:get: method, Facebook iOS SDK rebuild the real url base on yours. So, the url you passed will not get into the webview finally. What you need to do is implementing a method in FBDialog.m like this:
-(void)hackLoadURL:(NSString*)url withDelegate:(id)delegate {
_webView.delegate = delegate;
[_webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
}
The second problem is that you need to hack the
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
delegate method and replaced with the one you make implementation. But in order to keep the original Facebook SDK works, you need to add below code to FBDialog.m
_webView.delegate = self;
within -loadURL:get: method, and before this line
[_webView loadRequest:request];
finally, you need to implement
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
yourselves in your class, and use
FBDialog *dlg = [FBDialog new];
[dlg hackLoadURL: yourExpectUrl withDelegate: self];
to do what you wanted.

How can i know web view is loading completed

i have web view in that i am loading pdf file .
pdf file has 2 mb size so it tacking time. i want to add indicator .
for that how can i know my file is loaded in web view ? ...
UIWebViewDelegate
in particular:
- (void)webViewDidFinishLoad:(UIWebView *)webView
James P has the right answer (^'ed), but here is the code to show and hide the indicator.
After you've registered with the UIWebViewDelegate...
- (void)webViewDidStartLoad:(UIWebView *)webView {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
// Other stuff...
}
And then
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
// Other stuff...
}
Also you probably want to check for failures and hide the activity indicator there as well...
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
// Other stuff...
}
first Add the delegate "UIWebViewDelegate", then you can use the below methods.
– webView:shouldStartLoadWithRequest:navigationType:
– webViewDidStartLoad:
– webViewDidFinishLoad:
– webView:didFailLoadWithError:
You could pull your PDF down using ASIHTTPRequest, which would let you set up a progress bar showing real progress, and then feed it to your UIWebView once it's downloaded.
EDIT: ASIHTTPRequest is a free third-party library that provides a MUCH improved interface to iOS HTTP client functions. LOTS of code samples and instructions here: http://allseeing-i.com/ASIHTTPRequest/How-to-use

iPhone UIWebView - Open new UIWebView Controller from a hyperlink

I have an embedded website that has many links but the webview window is fairly small to allow for a larger image above the list to be zoomed in and out. I need the webview to respond to hyperlinks into a new controller view with a second embedded UIWebView if at all possible.
The UIWebView has a delegate wich allows you to respond to certain events, e.g. a request to load new content. Just implement the following in your delegate-class
-(bool) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
//You might need to set up a interceptLinks-Bool since you don't want to intercept the initial loading of the content
if (self.interceptLinks) {
NSURL *url = request.URL;
//This launches your custom ViewController, replace it with your initialization-code
[YourBrowserViewController openBrowserWithUrl:url];
return NO;
}
//No need to intercept the initial request to fill the WebView
else {
self.interceptLinks = YES;
return YES;
}
}

UIWebView loading parsed html string

i'm building an app that will display some newsletters to the users. the newsletters are displayed in a uiWebView. I'm reading the url's for the newsletters from an rss feed. I parse the xml, and in a table view i have all the newsletters. When a cell is clicked the uiWebView is pushed and the newsletter is loaded. Because the uiWebView doesn't open links that have target=_blank i need to replace the _blank from target with "". In an NSOperation i download the contents of the html and after the download is finished i replace the strings like this:
NSMutableString *page = [[[NSMutableString alloc] initWithData:pageData encoding:NSISOLatin1StringEncoding] autorelease]; [page replaceOccurrencesOfString:#"target=_blank" withString:#"target=""" options:0 range:NSMakeRange(0, [page length])];
after i do this i load the parsed string in the webView to display it to the user.
[myWebView loadHTMLString:page baseURL:[NSURL URLWithString:#""]];
while the NSOperation is downloading the contents of the page an HUD with a activity indicator and a label that says Loading is showed. When the download is finished the HUD is removed from the superview.
so far so good..but here come the questions. i used the NSOperation with the callback function because i wasn't able to determine the last call to webDidFinishLoading ( i read this UIWebView - How to identify the "last" webViewDidFinishLoad message? - this is a part of my problem but the response was to use some Apple private classes and that is a problem for me). so i'm doing this:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
NSLog(#"WebViewSouldStartWithRequest: %#", urlString);
if (navigationType == UIWebViewNavigationTypeLinkClicked)
{
if(![urlString isEqualToString:#"about:blank"])
{
NSLog(#"FeedViewController: startPageLoad");
activityHud = [[HUDView alloc] initWithFrame:CGRectMake(110, 100, 80, 80)];
[activityHud setText:#"Loading"];
[myWebView addSubview:activityHud];
NSLog(#"FeedViewController: pageUrl = %#", urlString);
[self resetWebView];
[urlLoader loadPageFromUrl:request.URL withCallbackTarget:self withCallbackSelector:#selector(endLoading:)];
}
}
return NO;
}
- (void) endLoading:(NSMutableString *)page { [self resetWebView]; NSLog(#"FeedViewController: endLoading"); [activityHud removeFromSuperview]; [myWebView loadHTMLString:page baseURL:[NSURL URLWithString:#""]]; }
after i touch a cell in the table view and the newsletter is showed it looks like it should, when i click a link in the newsletter, the page is loaded with the new request, parsed but visually is not looking as it should (i looked at the page after parsing in NSLog and it has the css styles and html tags, head, body opened and closed correctly) anyone had this problem with uiWebView, not showing webpages correctly?
i tried loading the page with - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType{ return YES; }
and in - (void)webViewDidFinishLoad:(UIWebView *)webview {} and in - webViewDiStartLoad
but the methods are being called for every item that is loaded in the webview so showing and hiding the HUD in those method is not a good solution.
I encountered some problems while using - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { ... return NO }
for example links that have paths like this /bilder-galerien to not work and in NSLog i receive this for them
Unknown scheme, doing nothing:
/bilder-galerien
but when i use
(BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { return Yes } and didstartLoading and finishLoading the urls are loaded and i don't know why...
another problem are the special german characters..in my first load(after pressing a cell in the uiTableView) the page is parsed like it should be by the uiWebView but after i click a link and the corresponding request is loaded also the characters are not parsed correctly..
can anyone point me in the good direction? thank you in advance
UIWebView doesn't open target="_blank" links. Certain links don't fire UIWebViewNavigationTypeLinkClicked events. This happens when the link has the target="_blank" attribute.
To work around this problem i used the code below. It injects some javascript after the page load to remove the target attribute from all the links. After using this code i didn;t needed anymore to parse the html source and replace _blank with _self for example.
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *js = #"\
var d = document.getElementsByTagName('a');\
for (var i = 0; i < d.length; i++) {\
if (d[i].getAttribute('target') == '_blank') {\
d[i].removeAttribute('target');\
}\
}\
";
[webView stringByEvaluatingJavaScriptFromString:js];
}
I like SorinA answer, we can make it even better by:
avoid obstructing javascript with var d
as we know we're running webkit engine we can use selectors:
...so in your UIWebViewDelegate protocol method invoke js code:
- (void) webViewDidFinishLoad: (UIWebView *) webView {
[webView stringByEvaluatingJavaScriptFromString: #"(function($){for(var i=0;i<$.length;++i){$[i].removeAttribute('target')}})(document.querySelectorAll('a[target=_blank]'))"];
}