views:

3401

answers:

4

Hi all,

I'm building an iPhone app with a UITableView. On selecting a row, I'd like a UIWebView to be pushed in loading a specific URL.

I currently have:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath  {
NSDictionary * story = [stories objectAtIndex:[indexPath row]]; 
NSString * storyLink = [NSString stringWithFormat:[story objectForKey:@"link"]];

 [[self navigationController] pushViewController:[[FirstViewController alloc] initWithNibName:@"FirstView" bundle:[NSBundle mainBundle]] animated:YES];
}

How can I get the new view that slides in to contain a UIWebView and subsequently load story link into it via:

loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:storyLink]]

Thanks in advance,

Benji

A: 

To get a uiwebview simply create it with Interface Builder or define it as a instance variable in the viewcontroller you are loading. After that using nsurlrequest will work

ennuikiller
A: 

The best way would be to create a new view controller class that contains a webview. That view controller would have a url property, which gets passed on the web view when in viewDidLoad.

Daniel Dickison
How can I add a url property to the view controller?
Benji Barash
Read [The Objective-C 2.0 Programming Language](http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html).
Daniel Dickison
A: 

First off, do you have a nib named "FirstView" in your project?

Second, the way I've usually done this is to instantiate the ViewController and pass the parameters to it before pushing it onto the nav stack.

UIViewController *myViewController = [[FirstViewController alloc] initWithNibName:@"FirstView" bundle:[NSBundle mainBundle]];
myViewController.story = storyLink;
[[self navigationController] pushViewController:myViewController animated:YES];
kubi
Yeah I have a FirstView nib. Your example is throwing me up and error - request for member 'story' in something not a structure or union. I imagine it therefore doesn't like myViewController.story = storyLink;
Benji Barash
+5  A: 

As others have said, the general idea is to have a property on FirstViewController that stores the URL it needs to load, and then load that URL into the UIWebView when the view appears.

Here's an example of what it might look like, starting with the header:

@interface FirstViewController : UIViewController {
  UIWebView *webView;
  NSURL *storyURL;
}
@property (nonatomic, retain) IBOutlet UIWebView *webView; // this is set up in your nib
@property (nonatomic, retain) NSURL *storyURL;
@end

Now for the implementation:

@implementation FirstViewController

@synthesize webView;
@synthesize storyURL;

- (void)dealloc;
{
  [storyURL release]; // don't forget to release this
  [super dealloc];
}

- (void)viewDidAppear:(BOOL)animated;
{
  // when the view appears, create a URL request from the storyURL
  // and load it into the web view
  NSURLRequest *request = [NSURLRequest requestWithURL:self.storyURL];
  [self.webView loadRequest:request];
}

- (void)viewWillDisappear:(BOOL)animated;
{
  // there is no point in continuing with the request load
  // if somebody leaves this screen before its finished
  [self.webView stopLoading];
}
@end

So now all you need to do in the controller for the previous view is get the story URL, pass it on to FirstViewController and push it.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath  {
  NSDictionary *story = [stories objectAtIndex:[indexPath row]]; 
  NSURL *storyURL = [NSURL URLWithString:[story objectForKey:@"link"]];
  FirstViewController *firstViewController = [[FirstViewController alloc] initWithNibName:@"FirstView" bundle:[NSBundle mainBundle]]; // I'm pretty sure you don't need to pass in the main bundle here
  firstViewController.storyURL = storyURL;
  [self.navigationController pushViewController:firstViewController animated:YES];
  [firstViewController release]; // don't leak memory
}

And that's about it. A few other points:

  • I assume the "link" value in your dictionary is already a string - the construction of a brand new string in your original example was unnecessary if this is the case. As you can see in my example, we can use this string directly to create the NSURL instance.

  • In your original code, when you alloc/init your FirstViewController, you pass this straight into pushViewController. This creates a memory leak as once UINavigationController is done with it (after it gets popped off the navigation stack), it's retain count will still be 1. At the least you should call autorelease but the most efficient thing to do here is simply alloc/init it, store it in a temp variable, then call release straight after we've pushed it. This ensures that once it gets popped off the navigation stack, it will get deallocated.

Luke Redpath
Awesome explanation - thanks a lot!
Benji Barash
I would do the `loadRequest` during `viewDidLoad` rather than `viewDidAppear` -- otherwise, you'll keep reloading the page if e.g. you have a tab controller that can switch the view in and out.
Daniel Dickison