I'm getting a little confused about when I should use a NIB file and when I should use code.
Here's my problem :
I have a navigation based application with a RootController and its NIB file.
The RootController's NIB file contains a TableView.
When I click on a cell I initialize a new connection with a request to load content.
When the connection has finished loading I create a new postViewController (custom) from a NIB file and I push it on the navigationController viewController stack like that :
PostViewController *postViewController = [[PostViewController alloc] initWithNibName:#"PostViewController" bundle:[NSBundle mainBundle]];
[postViewController.webView setDelegate:self];
postViewController.postContent = [[postsData objectForKey:#"post"] objectForKey:#"content"];
[self.navigationController pushViewController:postViewController animated:YES];
[PostViewController release];
Then, as you can see I try to set the rootViewController as the delegate for the webView in order to be able to intercept a click on a link and push a new ViewController on the stack. I need that new view to have the navigation bar with the back button.
Problem : looks like the setDelegate isn't working because the webView:shouldStartLoadWithRequest:navigationType never gets called !
I guess I should set the delegate in the NIB file but I have no idea how. The NIB file from PostViewController doesn't know about the RootViewController...
Here are screenshots of the NIB files :
If you need more detail just ask me.
Thanks a lot...for helping me not banging my head for another day :)
Make sure postViewController.webView isn't nil when you call setDelegate: on it. Also make sure it isn't being called anywhere else, and make sure the delegate outlet isn't connected to anything in your NIB.
A couple other comments:
It's a bit unusual to use your root view controller as the webview's delegate in a case like this. It should work, but it might make more sense to move those delegate methods down into your PostViewController. From there you can still intercept the link clicks and call [self.navigationController pushViewController:animated:].
[PostViewController release] is releasing the class object. Not a good idea. Instead you should be calling [postViewController release].
[postViewController.webView setDelegate:self]; sets the delegate for the current Controller not postViewController. Try:
[postViewController.webView setDelegate:postViewController];
And you can put this line below pushViewController:animated: then the webView should already exist.
Related
I am a newbie to iOS world and have started building custom code on top of a templated code.
So excuse me for the obvious.
The View chain starts with a MainWindow.xib which contains a App Delegate Object, a Window Object and Application ViewController. I dont understand why those objects are needed over there. But what I understand, I need to mention starting ViewController in the "Nib Name" Property to initiate my custom View Controller (called "EmptyViewController"). Its a dummy view controller, just there to avoid crash to happen as a result of missing valid viewcontroller.
I initiate a separate Modal View Controller(MainViewController) inside didFinishLaunchingWithOptions.
Code for initiating modal View Controller --
self.window.rootViewController = self.viewController;
mainView = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
// present the viewcontroller
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:mainView];
[self.viewController presentModalViewController:navController animated:NO];
// release it, because it's retained as modalViewController
[navController release];
I do not put this MainViewController inside MainWindow.xib as I want to have navigation at the root of MainViewController.
Inside MainViewController, I push HelpViewController when "help" button is pressed.
But HelpViewController does not show any navigation bar. I do not understand why?
Code for Pushing Navigation bar --
HelpViewController *helpVC = [[HelpViewController alloc] init];
[self.navigationController pushViewController:helpVC animated:YES];
[helpVC release];
So I would like to understand --
1) Why is MainWindow.xib needed? Can I remove it? (Note: I tried to remove it, but then I get blank screen)
1.a) Why are all the controls/objects App Delegate Object, a Window Object and Application ViewController objects needed?
2) Why doesnt HelpViewController show Navigation bar?
3) Another thing I noticed, if I say self.presentingViewController, EmptyViewController handle is returned while popViewController returns me back to MainViewController.
Thanks
The App Delegate simply implements some app-level 'callbacks' by which iOS communicates with your own code. In main.m you can see how iOS is told which of your classes implements UIApplicationDelegate. iOS creates an instance of this class and call these delegate methods ('callback') whenever appropriate (e.g. when the app goes to background).
The Window is something iOS provides, your app needs to tell what to display on it. And, as you saw, this is usually done in didFinishLaunchingWithOptions (which is called by iOS to inform your app things are ready to get started).
A View Controller is a class that handles states of stuff you show on the Window. You don't show stuff directly on the Window, but instead use Views. Every View Controller has a View with UI elements.
The XIB or NIB is a UI description/layout file. A XIB and View are linked together; you need to tell the XIB to which View Controller member (e.g. a UILabel) a UI element belongs, and you tell the XIB which View Controller method to call on a certain UI event (e.g. user taps on a button).
These are the basics. I'm aware it does not answer all your questions; I suggest you read the very good Apple documentation. Don't try to understand everything immediately as things, as you're experiencing, indeed can seem illogical at start.
Let me try and explain this. Within a project folder has .m and .h files (we all know that haha) however when you start a new ".m" with a xib like for example:
ViewTwoController *loginView = [[ViewTwoController alloc] initWithNibName:#"contentscreen" bundle:nil];
[self presentModalViewController:loginView animated:YES];
[loginView release];
I was wondering how do I create a method that runs as soon as that class (if I can call it that, I'm new to objective C) similar to a main method that Java would have. I want to run some code as soon as that .m has been called and started. Any help would be valued thanks :)
To be safe try to put this in - (void)viewDidLoad
Everything that happens here happens when the view is loaded onto the screen.
Note that there are number of places where you can put your method, in viewWillAppear or in your AppDelegate etc. But I found putting UI elements like your login popup better in viewDidLoad
Hope this helps...
You can add additional code in viewDidLoad method, which is called as soon as your view controller has been loaded.
Using the initWithNibName:bundle: method, your view controller will be automatically loaded and initialized.
I have a design question/technical question about my iPhone app.
I have a pretty simple (read really really simple) single view application. And it does everything that I need it to do. However I find myself in need of a help view. And I really don't quite know what to do!
I have a simple helpButton() method in my main view controller, and I really just want to display a scrollview with a bunch of images that show what to do during the use of my app. However, should I make a new viewcontroller class? How do I call it from my method?
Really I was thinking of an unfortunately simple method, just putting a scrollview behind everything and hiding it. Then showing it when the IBAction is called. Horrible...
Sorry if this is elementary, I haven't needed to do anything more yet!
You can push a modalViewController. To do that just make a new viewController with the scrollview and associated data in it, then
MyViewController *myViewController = [[MyViewController alloc] init];
[self presentModalViewController:myViewController animated:YES];
Create an IBAction in your new viewController and a hooked up button to that action to dismiss the modalView (something like this:
IBAction done {
[self dismissModalViewControllerAnimated:YES];
}
A couple options:
1) Create a new UIView object, either programmatically, or even in your existing XIB file. Use the [self.view addSubview:view] method to display it.
2) Create a new UIViewController with its own XIB file. Use [self presentModalViewController:anaimated:] to display it.
Either way, you'll need to add something to the new view to dismiss it when you're done.
Basically, what I want is to be able to press a record in a table, and have it push to another view.
To do this, I created a nib file and a UIViewController subclass (for the "pushed" view). I set the nib file's "File Owner" to be the controller I created. EDIT: I also then set the "view" field of the controller to be the View. Then, in the view controller of the table that will push that view, I set the didSelectRowIndexAtPath: method to include the following:
SearchTableController *vc = [[SearchTableController alloc] initWithNibName:#"SearchTable" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:vc animated:YES];
[vc release];
(where "SearchTableController" is the name of the UIViewController subclass and "SearchTable" is the name of the nib file)
However, when I run this code and click on the record, nothing happens- the app doesn't crash, but the view doesn't get pushed. The code is getting run, because it works when I NSLog(), but it doesn't seem to be pushing the view.
Thanks for any help in advance.
You are really close, but did you tie the view in the nib file to the view field of the view controller?
EDIT: So the view is connected, and your code looks just fine. I just pulled a piece of my own code:
// show theme settings
ThemeController * theme = [[[ThemeController alloc]
initWithStyle:UITableViewStyleGrouped] autorelease];
[[self navigationController] pushViewController:theme animated:YES];
Have you checked if self.navigationController is non-nil?
Couple of things I'd try at this point:
just hard-code the view to come up as the root view, verify it works
put a couple of NSLogs in the viewWillLoad, viewDidLoad, viewWillAppear in the client view controller
Best of luck.
I shift to my view by
[[self navigationController] popToViewController:controller animated:YES];
In that ViewController, I'm not able to get a notice, that it comes back to front (e.g. by viewWillAppear). I want to reload a table, as soon as the view is visible again.
How do I get a notice, that the view comes back on the screen?
----> solved: See my last comment on Corey's answer
viewWillAppear should be called if you are using a UINavigationController.
Are you sure you have added it correctly to the view hierarchy?
Did you check if viewWillDisappear gets called when it goes offscreen?
Did you try viewDidAppear just to make sure?
Did you spell the method name correctly?
To add:
Is the instance of UINavigationController added directly to the UIWindow instance?
The delegate methods like viewWillappear are sent from UIApplication (I believe). UIApplication only "knows" about viewControllers whose views are either:
Added Directly to UIWindow.
Added to a
UINavigationController/UITabBarCOntroller
that is added directly to UIWindow
(or a chain of these that leads to UIWindow).