I just found out that NavigationControllers have the property topViewController; this is the viewcontroller that is shown (it's top of the stack).
Its a read-only property though. I then noticed that there are two options:
1) create the NavigationController from code and use initWithRootViewController and refer to the ViewController that you want to have shown.
// look at the code example at page 32 (creating a navigation contr.) in the "View Controller Programming guide"
2) create the root controller - just like GroupController as stated in the example on page 32 - and then PUSH this rootcontroller to the Navigationcontroller (animated:NO) that is already existing (because it was created using IB).
btw: i moved my Navigationcontroller to the first XIB file so i can push and pop views centrally instead from the second XIB. i then created an IBOutlet so i could refer to the Navigationcontroller and push the view.
Your should have ViewController for every tab that you need. So if you want five tab bar items you need 5 view controllers and 5 nib files. Say, ViewOne.xib, ViewTwo.xib and so on..
All the nib files need to have their file owner as the ViewControllers. So ViewOne will have ViewOneController as its file owner. Add a tab bar and a tab item to each one of the view in IB.
And in your AppDelegate, you would initialize your view controller from the nib and add it to the tab bar controllers in the MainWindow.xib nib file
I am using IB. I have done the separate controllers, they're working fine, and I'm intercepting actions from some test buttons I have set up in each of the controllers.
However, I can't seem to figure out how to connect my outlets? In other words, I need to be able to change the text in a label in a particular view, and I can't seem to figure out how to attach that label to any of my classes within IB.
I assume I have to subclass UIView? How does that work with my separate .xib files? I'm a bit confused around the edges here.
UITableView with UITabController - Not using Interface Builder
Hi there,
Thanks for all the great posts on this thread, it has been very useful to me.
I want to be able to write iPhone apps without using Interface Builder, or at least very rarely use IB.
I have attached my project to this post.
I am having trouble figuring out how to set the UITableView delegate/datasource and get it working. When i run the app as it is, i get the following error:
-[TabBarTestAppDelegate tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x44e840
This happens when i try and enter the second View in the UITabBar (the one named All Recipes. The other tabs are all fine because they dont actually do anything.
My understanding is that the UITableView needs to be assigned a datasource and delegate in order to implement the required methods to be able to display anything.
If anyone can offer some suggestions with this it would be very much appreciated.
I am using IB. I have done the separate controllers, they're working fine, and I'm intercepting actions from some test buttons I have set up in each of the controllers.
However, I can't seem to figure out how to connect my outlets? In other words, I need to be able to change the text in a label in a particular view, and I can't seem to figure out how to attach that label to any of my classes within IB.
I assume I have to subclass UIView? How does that work with my separate .xib files? I'm a bit confused around the edges here.
Thanks, this thread is great!
Jolly
Jolly. I try to give an example using the viewOne as our subject:
in the ViewOne.XIB set the File's Owner class as ViewOneController (via the last tab in the inspector - Class identity section).
Create IBOutlets(in .h file, along with @property, and in .M file use @synthesize) in the ViewOneController for each IB field,label etc that you need to change/read. In IB you can now connect the label to the File's Owner and select the IBOutlet corresponding to the item you select.
f.i:
//.h file
IBOutlet UILabel *mylabel;
} //end of class definition
Thanks for the advice. Actually, I'd already figured it out.
Basically, in IB, ensure that the Inspector window is open, and the little blue "i" is selected. Click on the "File's Owner" icon. Go to the inspector window, and select the class you wrote (in my case, a UIViewController subclass called "StatusController." That has the outlets that I was expecting, allows me to connect them, and works as expected.
I'm a bit new to IB3, which is radically different ( and *tons* better ) than IB2.
Ok I have a question somewhat related to this. I have a Table view with a navigation controller. If the user clicks the plus sign I go to a detail view which still has the navigation bar at the top. I add a 'Save' bar button item to the top which works fine, I just need to know how to return to the table view after the user clicks it. Is there a method I can call that returns a navigation controller back to the root?
To view these messages, all you have to do is go to spotlight in the top right hand corner of your screen and type in UINavigationController.h and find that file. open it up. You will see the properties of the class declared, and also the methods (or messages you send to it) also declared there.
Do that for any class you want to find how to get access to the properties of and you will probably notice that you can actually do a lot more than you think with most classes.
Also, remember, these classes are subclasses of something else and inherit everything from the higher classes, so you wanna do something to a UITableView, but theres no obvious method, and there is in UIScrollView, then you need to realise that UITableView is just a subclass of UIScrollView and retains every property and method of the higher class. Don't be afraid to go searching higher up if you don't find the ways to do things. Look for something like this: UITableView : UIScrollView and that tells you that UITableView, the view who's class header file you are looking at, also adopts the nature of a scroll view, and you can search UIScrollView.h also for more stuff you can do to it.
This is what I am having trouble with.... I am at my root view... then I create the next view with the toolbar and push it into view. So lets call the root level 1 and the view it pushes level 2. I have about 4-5 levels total... when the user is on level 5 I want them to be able to click the tool bar and jump up to level 2 instead of pressing back 3 times...
The problem is that I create level 2 inside of level 1 and push its view. Pressing the button inside of level 2 should do nothing... until your are at level 3. The problem is that when I set the action for pressing the button in level 1 the level 2 view has not yet been created so it doesnt like me doing that...
My popToLevelTwoView function does not work... it works if I say :self but then it pops to level 1 not level 2.... and if I create it inside of level two when it loads it does not get created correctly.... maybe I am pushing my views all wrong?
OK... the way you're going about this is incorrect.
I can't be sure but this is how I would go about it:
Create a property in level 3 of the class LevelTwoViewController, and set like this: level3ViewController.number2ViewController = self;
then at level 3 tell level 4 that to set level4ViewController.number2ViewController = number2ViewController;
then at level 4 tell level 5 to set a property of it's own level5ViewController.number2ViewController = number2ViewController;
then in level 5 when the toolbar button is pressed, say:
[self.navigationController popToViewController:number2ViewController];
Does that make sense? Make each higher view have the second level as its property.
I dunno if that would work. If it doesn't, I'd use [[UIApplication sharedApplication] delegate] to drill down to find level 2 as a property of level 1. That would almost definitely work as its a singleton object (only references, doesn't create another object).
Then, alternately again, you could set it all up with view Controllers in a nib file and reference it via an IBOutlet.
Last edited by DevTeamOfOne; 11-05-2008 at 04:07 PM.
Tab Bar Controller and Navigation Controller Setup Using Interface Builder
I'm lucky to have stumbled across this thread a couple of days ago, and would like to than everyone for the information presented. I'm new to programming for the Mac/iPhone and have run into the following problem.
MainWindow.xib
I setup everything using IB (by following the video posted in this thread). My First Tab is set to a Navigation Controller (by clicking the status bar in IB). The view within the Navigation Controller is loaded from FirstView.xib.
FirstView.xib
In IB the File's Owner is FirstViewController (the view controller). I have a proxy object containing the App Delegate, a Table View displaying data, and a view controller for the detail (loaded from another xib file called Detail.xib after the selection is made). I've implemented the required methods to allow selection, and the table view is responding to click events.
When a row is clicked, I call the App Delegate and pass the text of the cell that was clicked. In the App Delegate I try to push the next view (detailController), but it doesn't load. The message is getting sent to the App Delegate but when I call pushViewController nothing happens. I don't get any compilation errors and as I click the cells they are highlighted.
I tried adding a Navigation Controller to FirstView.xib, deleting the proxy object used for the App Delegate and handling the pushing of the view in FirstView.xib's file owner but I get the same results.
Design wise; Should the app delegate be used to handle the pushing of views for each tab? Or would it be better handled by the file's owner of each xib loaded for each tab?
Any help would be appreciated. This is all very new to me. Thank you,
Thanks, how would I go about setting this up using IB? I removed the calls to the app delegate and moved the handling of pushing the view controller in FirstView.xib's File Owner (firstViewController). In IB I dragged a Navigation Controller and wired it to an outlet in firstViewController.
So now firstViewController has links to a tableView, detailController and the Navigation Controller. In the viewDidLoad method of firstViewController I put the following.
Am I heading in the right direction? I'm not getting any errors but nothing happens as well.
EDITED: After much headache I decided to try this using code and was successful. Surprisingly I was able to get a better understanding of Interface Builder doing it this way. If you're stuck trying something in IB, give it a try in code.
Last edited by jmartin113; 11-13-2008 at 06:34 PM.
Programatically adding new tab bar items on startup
Hello everyone.
I have viewed all that has been said in this thread about creating tabbars in code as well as in IB. I would like to keep using everything in IB because of the lazy loading aspects it offers.
What I need to be able to do is this:
1. At startup, a user logs in, and his/her role(s) is discovered. Once this info is known, for each role that he/her has rights, a separate tabbar item for each role is to be created that isolates (encapsulates) that role functionality into separate navcontroller/view controller stacks. Thus a role of "user" would have a tabbar item called "User" and likewise a role of "admin" would have a tabbar item called "Admin".
I know this can be all done programatically, but is there a way to do this using IB allowing dynamically adding ONLY the appropriate tab items on-the-fly, only when this xib file is referenced instead of statically building the view with the tabbars items that would contain all possible roles?
A sample app project demonstrating this would be a huge help!
@interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UITabBarController *tabBarController;
MyTableViewController *myTableViewController;
MySecondTableViewController *mySecondTableViewController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) UITabBarController *tabBarController;
@property (nonatomic, retain) MyTableViewController *myTableViewController;
@property (nonatomic, retain) MySecondTableViewController *mySecondTableViewController;
@end
@implementation AppDelegate
@synthesize window, myTableViewController, mySecondTableViewController, tabBarController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
tabBarController = [[UITabBarController alloc] init]; // creates your tab bar so you can add everything else to it
myTableViewController = [[MyTableViewController alloc] init]; // creates your table view - this should be a UIViewController with a table view in it, or UITableViewController
UINavigationController *tableNavController = [[[UINavigationController alloc] initWithRootViewController:myTableViewController] autorelease];
[myTableViewController release]; // creates your table view's navigation controller, then adds the view controller you made. Note I then let go of the view controller as the navigation controller now holds onto it for me. This saves memory.
mySecondTableViewController = [[MySecondTableViewController alloc] init];
UINavigationController *table2NavController = [[[UINavigationController alloc] initWithRootViewController:mySecondTableViewController] autorelease];
[mySecondTableViewController release]; // does exactly the same as the first round, but for your second tab at the bottom of the bar.
tabBarController.viewControllers = [NSArray arrayWithObjects:tableNavController, table2NavController, nil]; add both of your navigation controllers to the tab bar. You can put as many controllers on as you like, but they will turn into the more button like in the iPod program.
[window addSubview:tabBarController.view]; // adds the tab bar's view property to the window
[window makeKeyAndVisible]; // makes the window visible
}
- (void)dealloc {
[tabBarController release];
[window release];
[super dealloc];
} // lets go of everything else, thats so your program doesn't create any leaks of memory.
@end
I just typed up this quick App Delegate to show you how to do it. Yes, you do have rights to use whatever part of it you wish, and yes, you can ask any questions you like.
Please do note:
a ) I release the table views because they have been retained by the Navigation Controllers. Thus, I have doubled up and am taking double the memory. Once you have a nav controller holding your view, drop it. This saves memory. These nav controllers are set to drop automattically with their autorelease so there is no leak issue.
b ) if you need to add only one item to your tabBar for some strange reason, or just to test, change "arrayWithObjects: blah, blah2, nil" to "arrayWithObject: blah" and drop the nil.
Does this help you???
I created a New XCode Project and pasted the above code in for the header and implementation files and I get nine errors building it....
I am sure there is one thing I am not doing since all the errors have to do with MyTableViewController and mySecondTableBiewController.
-I created a View Based Application...is that the problem?
-Am I supposed to do something in IB?
Please Help!
1) error: syntax error before 'MyTableViewController'
2) error: syntax error before 'MyTableViewController'
3) error: syntax error before 'MySecondTableViewController'
4)error: no declaration of property "myTableViewController" found in the interface
5) error: no declaration of property "mySecondTableViewController" found in the interface
6) error: 'myTableViewController' undeclared (first use in this function)
7) error: 'MyTableViewController' undeclared (first use in this function)
8) error: 'mySecondTableViewController' undeclared (first use in this function)
9) error: 'MySecondTableViewController' undeclared (first use in this function)
1. You should start with a window based application. I never start with anything else as they are usually IB rich and cumbersome.
2. Make sure you have created the classes and imported their header files into the app delegate's implementation file (.h's imported into appDelegate.m)
3. Make sure there are declarations in your appDelegate.h file of:
Would this approach work the other way around. Instead of a TabBarView with a NavigationView as one of the tabs. But going from a NavigationView to a TabBarView?
If you are interested, I am currently developing full tutorials and from-the-ground-up samples that show exactly each stage of building things into an application with tab bars, navigation bars, etc. Look out for it at TheBarcodeProject
I have one tabbarController in IB.
And 10 Navigationcontroller in it.(view controller tableViewController)
more is automatically displayed.
Now my problem is that
in configure (tabbar) page i dont want to edit all item(navigation controller or tabbar item) in it.
I'm having the same problem of trying to understand what's the best way to have a simple application with Navigator + TabBar + tableView.
This thread is quite long and with many requests in the middle, so quite hard to read.
Would it be possible to provide two samples, one done using IB and the other one programmatically.
Or suggest some samples already around.
I think this could help a lot of people on this subject that it really seems a major cause of pain when starting developing for Iphone.
Thanks a lot in advance
Um, I thought that information was already in this thread. First page has sample code, and like the third page had a link to a video to download showing it done in IB. I think post #78.
I initially followed the video to create the tab bar + navigation structure...but gave up because I couldn't use the self.navigationController prop to push more views..don't ask me why, I don't know...
I used the few lines of code shown in page 1, and works great.
Only one question: a nice thing of the IB approach is that you can easily set-up tabs and assign them some built-in default images. For example there are images for a search tab, favorites, most recent etc. etc.
I'd like to use those images, since they are the typical one...how can I reference them in code?? Thanks!