UIWebView not responsive - iphone

I'm having trouble intercepting URL clicks within a UIWebView. I've read around and found the most common problem is that links have a target="_blank" attribute to open in a new window, but mine have no such attribute. URLs are of the form "/word", where word is some arbitrary word. I'm also encoding them with %20 when necessary. My UIWebViewDelegate class doesn't even receive a shouldStartLoadWithRequest: event, just nothing happens. I've also tried inserting a button into the HTML, and these are unresponsive too.
Are there any other rules governing which URLs UIWebView will acknowledge? I've tried using an absolute URL (and even just "http://www.google.com"), and also replacing the entire string of HTML with just a valid link to google, but all to no avail. And the really odd thing is that I can find one link that will work - it can be clicked and I successfully catch the event, but there seems (I've looked pretty hard) to be nothing different between the HTML containing this link and the others.
Given that I'm new to the iPhone platform, I figure I may very well be doing something more fundamentally wrong. Flow through the app looks like this: the main view is a UITableViewController, which lets users select from a list of words. When a word is selected, a new UIViewController is created and pushed onto the screen. This is the view with a UIWebView, which displays data loaded from a SQLite database. Some relevant bits of code are below.
//move from the UITableViewController to UIViewController with UIWebView
DetailViewController *viewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
...
[self.navigationController pushViewController:viewController animated:YES];
//load HTML and display it in a UIWebView
NSString *output = [NSString stringWithFormat:#"%#%#%#",header,definition,footer];
[definitionView loadHTMLString:output baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];
Any help would be greatly appreciated - been pulling my hair out for a while with this one.

You should take a look at PhoneGap: http://phonegap.com/
PhoneGap does exactly this (basically it's a big giant UIWebViewDelegate that makes it possible to write JavaScript apps for the iPhone that are able to take advantage of the camera, GPS, accelerometer etc.). Download the source, open PhoneGap.xcodeproj in the 'iphone' folder, and take a look at class PhoneGapDelegate. This is a great example usage of UIWebViewDelegate, hard to find a better example :) And it works of course.

Related

UIWebView loading and general performance

I am using UIWebView to display textual content in my app (I store the content in local HTML files that I pack with the app). All together, I have three web views whose content I change dynamically based on user feedback.
Although some might argue that this is not the most accepted way, I find UIWebView very convenient to display formatted text, and modify that text using HTML if necessary. While this works 99% of the time, on occasion, I experience problems that generally fall into one of these categories:
Sometimes, the web view content loads slow and is late a second or so.
The content loads but is not showing. However, as long as, I touch the view (try to scroll or something) the content pops in.
A few times I received memory warnings (usually not long after the app's initial loading) that in no way affected the performance of my app. It logged the memory warning but the app worked like nothing happened.
This is the method I use to load content to my web views:
- (void)loadSimpleDocument:(NSString*)documentName inView:(UIWebView*)webView
{
NSString *path = [[NSBundle mainBundle] pathForResource:documentName ofType:#"html"];
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
}
Aside from this, the shouldStartLoadWithRequest delegate method is also implemented, always returning a YES.
My question is: Is there a way to improve the reliability/performance of my web views (in particular loading)? Is there something I have overlooked, did wrong, or do not know about?
Some additional info:
I am on iOS6 SDK, use ARC, and do everything programmatically (do not use IB or storyboard).
You have 2 options to check what's going on:
Implement webViewDidStartLoad & webViewDidFinishLoad delegate methods to check why the content isn't showing (may be the content isn't loaded yet).
read the html content to an NSString then use loadHTMLString:baseURL instead of using loadRequest and check if it loads faster.
Hope this could help.

YouTube In WebVIew - iPhone

This is very strange to me...
I have a simple WebView that loads and interacts with the user exactly like safari mobile (iPhone). Now when you visit m.youtube.com in safari, the url changes when you click on a link to something like this...
http://m.youtube.com/watch?gl=US&hl=en&client=mv-google&v=HX6SyoZ5kw8
The problem with this is I don't think that url is being used in my webview... What do I mean? The following code is used to load a url every time the user try's to click on a link, and it works, but I have a problem with Youtube...
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
NSLog(#"%#",urlString);
VideoURLTextBox.text = urlString;
return YES;
}
When I first start up the webview it loads m.youtube.com and NSLogs() it into my console, but when I decide to click on a video it fails to NSLog() therefore I don't think a new url is being loaded, but when you load m.youtube.com in safari and click on a video you load a url like above, so why does this not NSLog() in my iPhone application?
What your probably seeing is that the youtube video is running javascript to play the video, you'd have to intercept the javascript callbacks to see that. Here's a link to the youtube video player api, detailing the callbacks, https://developers.google.com/youtube/js_api_reference#SubscribingEvents
If you just want to embed a youtube video in an iOS application then use this.
Using the mobile YouTube site isn't great, I had lots of problems with it in the past and ended up making a UIWebView category. I came across your question and decided to throw it on github :-)
https://github.com/enigmaticflare/UIWebView-YouTube--iOS-Category--ARC-compliant-code
UIWebView+YouTube iOS category to simplify loading youtube videos.
Instructions
1) Add these files to your project
UIWebView+YouTube.h
UIWebView+YouTube.m
2) Initiate UIWebView for example
#property (strong, nonatomic) UIWebView *webView;
#synthesize webView = _webView
_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0,0,212,172];
//set the X,Y origin of CGRect to where you want the webView to appear.
_webView.delegate = self;
[_webView loadYouTubeVideoID:#"gR8dO7Cln6M"];
[self.view addSubView:_webView];
Good luck, hope this is what your looking for :)
Adam
m.youtube.com is one giant java web app, delegate methods won't get called, presumably because any loading is written directly to the DOM in the UIWebView. Ran into this problem at work, not sure of the fix but there may be a way to inject the source with a JS click handler.

How to create a button that links to Safari?

For legal reasons, I'm obligated to show Terms of Service in my application, a PDF on an external server. What I believe would be easiest to do would be to create a UIBarButton item and then create an IBAction that launches the link in Safari.
So I create a button:
IBOutlet UIBarButtonItem *legal;
Then I make it into a nonatomic property and synthesize it in my implementation file, right? I go on to create an IBAction:
-(IBAction)legalButtonPressed:(id)sender;
I go into my implementation file, and here's where the issue comes. When it comes to defining those actions, I become confused. As I am new to iOS development, I could use some guidance. I don't know how to force the link into safari in the action. Any help would be greatly appreciated!
Thanks!
IBOutlet and IBActions are used for Interface Builder connections. If you have your UIBarButtonItem on a xib file, you can connect its action to the controller by right clicking in the files owner object. The same with the outlet.
Once you have the action in the controller connected to the button in the xib file, (I see no need to get an outlet here), you just implement the method as follows:
-(IBAction)legalButtonPressed:(id)sender {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: #"http://yourdomain.com/legal.pdf"]];
}
this will automatically open safari with the given url
Take a look at UIApplication's documentation, it has a openURL method you might find useful.
Another option is to include your legal text in a UITextView.
Example:
By clicking Join you agree to company's
Terms of Service, found here: http://www.site.com/tos.html and
Privacy Policy, found here: http://www.site.com/privacy.html
Make sure Link Detection is turned on in the UITextView and it will automatically recognize URLs. Any clicks on those URLs will automatically launch Safari.
Although you can do this approach (i.e. launch the link in Safari). I would suggest that you try to keep the user as much as possible in your app. I am guessing this LEGAL TERMS is a HTML doc?
You can do that using UIWebView. Init a webView and do this -
NSURL *url = [NSURL URLWithString:webAddress];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
[webView loadRequest:req];
This will open the url in your app only! You can make the UIWebView open up as a modal window or in many other ways...

Put a link on home screen of my app and connect it to WebView

In my app i want to put my website's url on home screen and on clicking on it i want it to be open as a WebView.
How should i go for this.
Thanks,
Previous commenter is incorrect. You can open any hyperlink either externally with Safari or internally with a UIWebView.
Add a UIWebViewController to your project. Then, instantiate an instance of a the UIWebViewController that will be shown inside your app--you'll do this by declaring a property & synthesizing it within your main view controller (which will need to be declared as a UIWebViewDelegate), such as:
#interface MyMainViewController: UIViewController <UIWebViewDelegate> {
// Your implementation code here
}
When a user taps the button (assuming you make it a button, rather than just a text hyperlink), you instruct your app to add the UIWebView to the view stack, loading the correct link. You'll want to either do this within a modal view or within a navigation stack so your users can get back out of the web view, of course.
In your MyMainViewController implementation file, something like this:
-(void) showWebView {
// NOTE: I have not tested this, just prototyping
// off the top of my head
UIWebView *myWebView = [[UIWebView alloc] init];
myWebView.delegate = self;
NSURL *homeUrl = [[NSURL alloc] initWithString:#"http://example.com"];
NSURLRequest *homeRequest = [NSURLRequest requestWithURL:homeURL];
[myWebView loadRequest:homeRequest];
[self.presentModalViewController: myWebView animated:YES];
// Don't forget to release objects when you're done
[myWebView release]; // etc.
}
Now, this is off the top of my head from what I know and have done. But I hope you get the general idea. I offer no warranty of any kind here, but do guarantee this is entirely possible with minimal headache. If you get stuck, check out the developer references for UIWebView. Apple's docs are top-notch & show great examples to get you up and running quickly.
Best.

Reused UIWebView showing previous loaded content for a brief second on iPhone

In one of my apps I reuse a webview. Each time the user enters a certain view on reload cached data to the webview using the method :-
- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
and I wait for the callback call
- (void) webViewDidFinishLoad:(UIWebView *)webView.
In the mean time I hide the webview and show a 'loading' label.
Only when I receive webViewDidFinishLoad do I show the webview.
Many times what happens I see the previous data that was loaded to the webview for a brief second before the new data I loaded kicks in.
I already added a delay of 0.2 seconds before showing the webview but it didn't help.
Instead of solving this by adding more time to the delay does anyone know how to solve this issue or maybe clear old data from a webview without release and allocating it every time?
Thanks malaki1974, in my case I wasn't using a modal view.
When I sat with an Apple engineer on WWDC 2010 and asked him this question his answer was simply: "Don't reuse UIWebViews, that's not how they were ment to be used."
Since then I make sure to calls this set of lines before allocating a new UIWebView
[self.myWebView removeFromSuperview];
self.myWebView.delegate = nil;
[self.myWebView stopLoading];
[self.myWebView release];
That solved the issue.
Clear the contents of the webview before you try to load new content
[self loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"about:blank"]]];
First, the UIWebView renders it contents in a background thread. Even when you receive webViewDidFinishLoad: it might not be completely done. Specially if it is an ajax-intense page that comes from the network.
You say you are hiding the view. I wonder if that means that the webview delays its drawing completely. What you could try is to move the UIWebView offscreen or obscure it with another view. Maybe that will change it's drawing behaviour.
If you do not need an interactive UIWebView then you can also consider to do it completely offscreen in a separate UIWindow and then create an image from that UIWebView's layer.
That's what I do, and it works:
[_webView stringByEvaluatingJavaScriptFromString:#"document.open();document.close();"];
Try loading a local file that is blank or has a loading graphic when you hide it, rather than just loading new content when you show it. Since the file is local it will be quick and even if the new page takes a while to load it will have either blank or loading expected behavior.
If you got controll over the html. You can communicate back to objective-c when the document is ready. Like so in jQuery:
function messageNative (name, string) {
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", "appscheme://" + name + "/" + string);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
$(function() {
messageNative('webview', 'ready');
});
And then in UIWebView's delegate method webView:shouldStartLoadWithRequest:navigationType: wait for the request with url equal to "appscheme://webview/ready". Then you should know: the document is loaded and ready for display. Then all that is missing is a simple fade-in or something like that :)