change the content of a UIWebView from another Controller - iphone

I have a TableViewController which is supposed to load a ViewController with a WebView in it when I select a cell.
Here's the code :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
PostViewController *postViewController = [[PostViewController alloc] initWithNibName:#"PostViewController" bundle:[NSBundle mainBundle]];
[postViewController.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.fr"]]]
[self.navigationController pushViewController:postViewController animated:YES];
[PostViewController release];
}
The problem is that the ViewController is loaded but nothing happens in the WebView.
When I debug the program I can see that the WebView's address is 0x0 so I guess something's wrong.
Is it because I try to modify the content of the WebView before its parent ViewController is loaded ?
I guess another way to do it properly would be to pass the URL to the ViewController and then to call loadRequest on the WebView from inside the viewWillAppear method.
But I need to understand why it doesn't work this way.

Try this
Instead of accessing the WebView why dont you just pass the URL value to the ViewController and load the Webview in the viewDidLoad of postViewController.
In your case
PostViewController *postViewController = [[PostViewController alloc] initWithNibName:#"PostViewController" bundle:[NSBundle mainBundle]];
postViewController.urlString = #"http://www.google.fr";
[self.navigationController pushViewController:postViewController animated:YES];
[PostViewController release];
In your postViewController.h declare the urlString with properties and synthesize in the .m file
Now in your viewDidLoad
//Alloc init your webview here
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]];

0x0 is the address of nil, meaning that your web view has not been initialized at this point.
If you're creating your web view in the loadView or viewDidLoad methods of PostViewController, then calling setNeedsLayout immediately after initialization will force its creation:
PostViewController *postViewController = [[PostViewController alloc] init ...
[postViewController.view setNeedsLayout];
Otherwise, these methods will not be called until your view is displayed.

Related

[viewcontroller_name tableView:cellForRowAtIndexPath:]: unrecognized selector sent to instance 0x7b3a630'

I am having an app which has a UITableViewController which is my settings page. I am pushing the UITableViewController with a presentModalViewController using self.navigationController (using storyboard ID). however each time I try to see that page, it's showing exception. After reading few posts I tried implementing two methods
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [super tableView:tableView
cellForRowAtIndexPath:indexPath];
return cell;
}
**my .h File**
#interface Setting : UITableViewController<UITableViewDelegate,UITableViewDataSource>
I have done all UI settings in IB so I didn't change anything in above two implemented methods.
In mainviewcontroller from where I am pushing the view to UITableViewController, I am using the below code
Setting *nextController = [[self storyboard] instantiateViewControllerWithIdentifier:#"setting"];
[self presentModalViewController:nextController animated:YES];
Setting *dvc = [[Setting alloc] init];
[self.navigationController pushViewController:dvc animated:YES];
As I already set all UIs in IB why do I need to implement those methods? At least I can seen the view correctly.
It looks like you're trying to initialize the same viewController twice. You don't need to alloc] init] after you instantiateViewControllerWithIdentifier. At least, from my experience you don't. Try this:
Setting *nextController = [[self storyboard] instantiateViewControllerWithIdentifier:#"setting"];
[self.navigationController pushViewController:nextController animated:YES];
That will "push" the nextController with the storyBoardID of "setting" from the right into your existing NavigationController.
However, using my intuition, I believe you want to present a settings view modally, that has it's own NavigationController. In that case, try this code, which wraps the Settings ViewController into a NavigationController, and presents that whole thing modally, so you can navigate within settings:
Setting *nextController = [self.storyboard instantiateViewControllerWithIdentifier:#"setting"];
UINavigationController *navcont = [[UINavigationController alloc] initWithRootViewController:nextController];
navcont.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:navcont animated:YES completion:nil];
Alternatively, you could do all of this in the Storyboard itself. Select your settings view controller, and go to Editor Menu > Embed In... > Navigation Controller. Then make a segue from your button to the navigation controller that holds the settings controller. Set the segue to "Modal" and you're all done.

uiwebviewdelegate not called from non-visible uiwebview

I am trying to avoid the blank white window that shows while a UIWebView loads content. Instead of putting a background on the UIWebView, I'd like to just put up a HUD on the current window and then push the new uiviewcontroller that contains the uiwebview when the content is loaded. Here's what I've done (code shortened for sanity's sake):
FirstView:
MyViewController *myVC = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
myVC.parentController = self.navigationController;
UIView *myView = [myVC view]; // Force view to load
MyViewController:
- (void)viewDidLoad
{
...
[myWebView setDelegate:self];
[myWebView loadHTMLString:htmlString baseURL:baseURL];
...
}
- (void) webViewDidFinishLoad:(UIWebView*) webView {
[parentController pushViewController:self animated:YES];
}
OK, so viewDidLoad is getting called, but none of the uiwebviewdelegate methods are getting called. However, if I push the view controller
FirstView:
MyViewController *myVC = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
[self.navigationController myVC animated:YES];
Then all of the uiwebviewdelegate methods in MyViewController do get called.
I'm stuck.
I don't know the specific requirements for your app, but it's usually a better practice to first push your view controller and then show the HUD on top of the new view controller while your content loads. You would add the HUD to the view controller's view in viewDidLoad, and remove the HUD in your webView's webViewDidFinishLoad callback method.
If you are not already doing so, make sure you are loading your web view's content in a background thread so as to not block the main UI thread while the content loads, otherwise it will appear to the user that your app has temporarily frozen.

need help with UINavigationController

I have a class called CataloguesEtTarifsPDFViewController which displays a tableView.
Now, inside this class I wanna create a UINavigationController and set the root of the UINavigationController this class:
Here is what I did:
CataloguesEtTarifsPDFViewController.h
UINavigationController *navigationController;
in the implementation file
CataloguesEtTarifsPDFViewController.m
- (void)viewDidLoad
{
CataloguesEtTarifsPDFViewController *catalog =[[CataloguesEtTarifsPDFViewController alloc] init];
loadingView.hidden=YES;
navigationController = [[UINavigationController alloc] initWithRootViewController:catalog];
}
When I click on the table cell I do this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
WebViewController *webViewController = [[WebViewController alloc] init];
[self.navigationController pushViewController:webViewController animated:YES];
[navigationController release];
}
But when I run and click on the tableView nothing happens...not view is showed up!!!Where am I going wrong?
IMPORTANT: I don't have a delegate file.Only CataloguesEtTarifsPDFViewController.h CataloguesEtTarifsPDFViewController.m and CataloguesEtTarifsPDFViewController.xib.
EDIT:
- (IBAction)showViewCataloguesEtTarifsPDF:(id)sender{
// Remove view to middleView
[mainMenuViewController removeViewsToMiddleView];
// create view controller
cataloguesEtTarifsPDFViewController = [[CataloguesEtTarifsPDFViewController alloc] init];
cataloguesEtTarifsPDFViewController.mainMenuViewController = mainMenuViewController;
// hide/show header button
[mainMenuViewController.headerViewController showMainMenuButton];
// highlight footer tabbar button
[mainMenuViewController.footerViewController.footerTabBar setSelectedItem:mainMenuViewController.footerViewController.footerTabBarItemMyAudi];
UINavigationController* navigationController = [[UINavigationController alloc] initWithRootViewController:cataloguesEtTarifsPDFViewController];
[self presentModalViewController:navigationController animated:YES];
}
You should probably read this: http://www.iosdevnotes.com/2011/03/uinavigationcontroller-tutorial/
Or this: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007457-CH1-SW1
Or watch this: http://peepcode.com/products/iphone-view-controllers-part-i
That'll give you the basics and you'll be well equipped to answer your question and fix your code :)
PS: You don't have to explicitly create and set a UINavigationController in your view controller. If the view controller is embedded within a navigation controller, the navigationController property of your view controller instance will automatically find it and return it.
What you're doing in viewDidLoad is wrong.
Wherever you are showing the CataloguesEtTarifsPDFViewController, you should wrap it in a UINavigationController there and show the UINavigationController instead.
This will make sure the navigationController property of UIViewController will be set.
In your tableView:didSelectRowAtIndexPath: method you should release the webViewController variable instead of the navigationController property.

Passing a string from IBAction to a separate View Controller

I am trying to pass a String from an IBAction in my DetailsViewController to the viewDidLoad in my WebViewController to call up a URL in the WebView.
Does anybody know how I can do this?
My Code:
// DetailsViewController.m
- (IBAction)edu1Link:(id)sender {
NSString *webURL = [[NSString webURL] initWithString:#"http://www.apple.com"];
_webViewController = [[WebViewController alloc]
initWithNibName:#"WebViewController" bundle:nil];
[[self navigationController] presentModalViewController:_webViewController animated:YES];
}
// WebViewController.m
- (void)viewDidLoad
{
[_webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:webURL]]];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
You could declare a property in your WebViewController and set that property in the action before presenting the view controller.
I guess the best way would be to use a delegate methode
here is a tutorial how you would do that
What albertamg is referring to is Objective-C properties. They are very powerful. Take a peak here: http://cocoacast.com/?q=node/103
Properties are like instance fields in Java. They're helpful in side-stepping zero-parameter-methods.

UIWebView delegate release confusion

Looking at the UIWebView docs, it says that
Before releasing an instance of UIWebView for which you have set a delegate, you must first set the UIWebView delegate property to nil before disposing of the UIWebView instance. This can be done, for example, in the dealloc method where you dispose of the UIWebView
I'm creating a webview on the fly on a UITableView cell tap. I'm not sure how to do the "set delegate to nil" bit, since I don't track the UIWebView after its pushed to the navigation stack. I would have though that the UIWebView's dealloc method would be calling release on the delegate anyway?
Here's what I'm doing:
UIWebView *webView = [[UIWebView alloc] init];
UIViewController *viewController = [[UIViewController alloc] init];
// Start the webview loading, etc
...
// set the delegate
[webView setDelegate:self];
// Add the webview to the viewcontroller
[viewController setView:webView];
[[self navigationController] pushViewController:viewController animated:YES];
[webView release];
[viewController release];
I get the impression that I should write
[webView release];
[viewController release];
[self release]; // Releasing the delegate as per the docs.
But that seems kind of awkward, or have I interpreted it correctly?
No. webView doesn't release/retain it's delegate it only assign it
UIWebView.h :
#property(nonatomic,assign) id<UIWebViewDelegate> delegate;
You can check [self retainCount] before and after [webView setDelegate:self]
It'll be the same
Just spotted this, old now but maybe an answer will be useful to someone.
The docs are correct, you should set the delegate reference to nil before releasing the webview.
In your code example, you would subclass UIViewController, and in the subclass override the -dealloc method to include a nullify of the view delegate.
For example:
- (void)dealloc {
// Clear the webview delegate
self.view.delegate = nil;
[super dealloc];
}
HTH