How do you create and manage a UIWebView object entirely in code? - iphone

I'm adding a UIWebView to my iOS App and I'd like it to open in response to a button getting clicked (so this code is going to be written in one of the button's event handler).
How can I create this UIWebView dynamically in code, position it to cover the entire screen and respond to events (e.g. to UIWEbView's shouldStartLoadWithRequest function so that the UIWebView can ask the native code to close the UIWebView).
I'd specifically like to avoid having to create stuff in Interface-Builder and it would be great if this could be reduced to several lines of code that could be later copy-pasted into other projects easily.

Simple:
UIWebView *webView = [[[UIWebView alloc] initWithFrame:self.view.bounds] autorelease];
webView.delegate = self;
[self.view addSubview:webView];

You just need to implement the WebViewDelegate's method in the controller, that you are making the delegate of the UIWebView.

Related

Preloading a UIWebView, avoiding white screen flash

I'm working on an app that has table navigation to eventually drill down to UIWebView that displays various information. However, the transition from the slickness of UITableView to the slow wonkiness of UIWebView is jarring for the user so I want to improve that experience however I can.
Specifically, the background of both the tableViews and UIWebView pages have black backgrounds, but when I open the UIWebView it flashes empty white for about a second (this is the case for both local and remote HTML files.) How can I (ideally) preload this process, or (at least) make the "flash" be all black rather than all white? I tried making the view / webView's background black but that didn't seem to help.
In my app right now, when a user selects a cell, the app just loads up the UIWebView subclass and pushes it on the navigation stack. The UIWebView subclass has an activity indicator that starts & stops animating on WebViewDidStartLoad and WebViewDidFinishLoad, which works fine, but it doesn't do anything to help the "white flash."
I have tested it... I'm sending the two method that I have used...
- (void)viewDidLoad {
[super viewDidLoad]; //objWebView is the outlet of UIWebView
[objWebView loadHTMLString:#"<html><body style=\"background-color:black;\"></body></html>" baseURL:nil];
//the more the delay the errors will be less so within 0.1-0.3 would be fine
[self performSelector:#selector(loadURL:) withObject:nil afterDelay:0.1];
}
-(void)loadURL:(id)sender{
[objWebView stopLoading]; //added this line to stop the previous request
NSURL *url = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
[objWebView loadRequest:req];
}
here I'm performing the request after 0.1 sec, other wise it will look white as in your case. Or you can give your delay time depending upon the time.. Cheers :)
Try in your
-(void)viewDidLoad{
myWebView.hidden = YES;
Then in
-(void)loadURL:(id)sender{
myWebView.hidden = NO;
I used:
[webView setHidden:YES];
[webView setDelegate:self];
when creating my webView and making the request and then added this delegate method to handle completed requests:
- (void) webViewDidFinishLoad:(UIWebView*)webView{
[webView setHidden:NO];
}
Successfully done it.
You have to create a view in Interface Builder first.
Then load the html to the webview using a initWithFrame in the init of your ViewController that contains the webview(this is where the magic happens):
CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
webView = [[UIWebView alloc] initWithFrame:webFrame];
Then simply load the webView into the view in viewWillAppear:
[viewWeb addSubview:webView];
This is really a question of interface designing, which is faster paint directly on the view or paint in a subview and then paint that subview in the view?
I had solved this problem years ago, using the common method of hiding the UIWebView behind a UIImageView, then removing the UIImageView after a delay.
But it suddenly came back, I think on iOS 7.0.4. It was occurring on a brand new iPad Air, as well as an older iPad mini non-retina. After two days of hair-pulling, I finally found a work-around.
Let's say you have webview which is restricted to landscape orientation, initialized like this:
WebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 1024.0f, 768.0f)];
And then you make it visible after pre-loading, with eg bringSubviewToFront or setHidden:NO on the webview (or alternatively with setHidden:YES or removeFromSuperview on the UIImageView). But instead of seamlessly switching the views, there's a flash and the background color blinks for about half a second.
The fix is to change the size of your webview, ever so slightly:
WebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 1024.01f, 768.0f)];
The problem and fix is highly reproducible. It works with a change as slight as the fourth decimal place (1024.0001f). At the fifth decimal place (1024.00001f), the flash returns. The value of the height (768.0f) didn't seem to matter.
Or, instead of working around the problem, you could just set the background color of your webview to whatever background color you're using. Unless you're using an image of course.

UIWebView loading but not displaying website (XCode 4, iOS SDK 4.3)

i'm going to write an app including an UIWebView. So first I wanted to try it out by just simply loading an URL.
Created the UIWebView in Interface Builder
Hooked up to the code
#property(nonatomic,retain) IBOutlet UIWebView *webView;
viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
if(!webView)
{
webView = [[UIWebView alloc]init];
}
webView.delegate = self;
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.com"]]]; }
also I implemented the didFailLoadWithError and webViewDidFinishLoad delegate methods.
webViewDidFinishLoad is called and indicating that HTML has been loaded.
Problem is: Even though webViewDidFinishLoad is called, the UIWebView doesn't display the website. It's only showing white color. The scroll bars right and at the bottom are shown when the UIWebView is touched and dragged but not content is visible. Nowhere found anything. Seems quite strange..
EDIT
This screenshot shows the connections of the xib:
Connections
If you hooked everything up in Interface Builder correctly, the following lines should not be needed:
if(!webView)
{
webView = [[UIWebView alloc]init];
}
webView.delegate = self;
Try removing them and see what happens. Also, put an NSLog(...) in the webView:didFailLoadWithError: callback and see if it is output.
I got it.. I used synthesize in the following way:
#synthesize webView = _webView;
So it was necessary to call the UIWebView in the following way:
[self.webView loadRequest:...];
New to this naming convention which is why i'm not used to necessity of self
Have you checked the File's Owner connect to the webView you declared?
Besides, webViewDidFinishLoad does not mean the HTML was loaded!
Whatever the content is loaded successful, this method will be called.

How can I prevent delayed display of my UIWebView

I must include some 'rich text' instructions* preceding a form; and thought adding a UIWebView to the header of the tableview would work. The HTML is a small file in my resources folder, the CSS is in a style tag in the file; so it's all nice and self contained.
The problem is, the view transitions in; then after a small delay the contents of the webview appear. The effect is jarring, and I don't think hiding the view and fading it in when it's ready would be any more desirable.
I'm creating the view with the code below, in my viewDidLoad method.
UIWebView * wv = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, HEADER_HEIGHT)];
[wv setBackgroundColor:[UIColor clearColor]];
[wv setOpaque:NO];
NSString *path = [[NSBundle mainBundle] pathForResource:#"HeaderMsg" ofType:#"html"];
assert(path != nil);
NSData *htmlData = [NSData dataWithContentsOfFile:path];
[wv loadData:htmlData MIMEType:#"text/html" textEncodingName:#"utf-8" baseURL:nil];
[self.tableView setTableHeaderView:wv];
[wv release];
I found 2 ugly workarounds, but I'm hoping someone has a better solution; since my workarounds make a real mess out of the code:
On previous screen when you make the
UIMYSCREENViewController, call a
[vc
preloadWebViewWithDelegate:self];
method which will make the webview
using the caller as the delegate.
The caller then retains the vc and
waits for the webview to sent it a
webviewDidFinishLoad method, at
which time it can present the view
and release the vc.
The calling view can make the webview,
wait for it to finish, then create the
new view and pass the webview into it.
At any rate, both of those "solutions" make me gag a little, so I'm hoping others have found a better way.
(*The instructions are mostly simple, styled text with some bullet points (no images or overly aggressive styling); but it takes about 14 carefully aligned UILabel views to simulate this without a webview - and is subject to the whims of the customer wanting to change the message.)
I would create another independent model or controller object to create and retain the webview, hopefully at a higher level and before (maybe during app init) displaying the view with the UI that could bring up the webview.
Consider this the same as pre-staging resources for an action game so that they don't have to be loaded during the game loop, which is a common design pattern.
Consider using this
https://github.com/Cocoanetics/DTCoreText/

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.

How to add refresh button to iPhone RSS Reader app?

I'm playing around with this application I got on last months Web Designer that's a very basic RSS reader. I would like to add a refresh button to the top navigation bar that refreshes all the content in the table but can't seem to work out how to do it. I've worked out it must somehow use the [tablename Reload] function, but have got no idea how to implement it.
I'm new to all this so simple instructions are good instructions :) I know how to add the button, its linking it to and defining the actions when the user clicks it that I'm struggling with.
You can grab the code here http://www.webdesignermag.co.uk/tutorial-files/issue-162-tutorial-files/ under iPhone Apps (it's the only one).
This is what you need to do in the RootViewController.m:
In the viewDidLoad function, add a button of type UIBarButtonSystemItemRefresh, associate to it an Action and a Target, (infact, as Alan told you, you need to learn about Outlets and Actions)
UIBarButtonItem *refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:#selector(refreshTable)];
self.navigationItem.rightBarButtonItem = refreshButton;
Implement refreshTable function (if not declared in .h, have to put it above viewDidLoad())
- (void)refreshTable{
[rssParser release];
rssParser = [[RSSXMLParser alloc] init];
[rssParser parseRSSFeed];
[self.tableView reloadData];
NSLog(#"table is refreshing ....");
}
Hi Graeme and velcome to SO.
For the iphone UI, you have to define outlets and actions, and use Interface Builder to link them together.
This page has some information that should hopefully get you started.
Understanding Outlets and Actions