Hey everyone, I'm at my wits end with this, and hopefully someone can help. I think this must be an Interface Builder bug, but let me know what you think and if you know a way around it.
Whenever I try to create a View in a tab bar based application that contains a Table View, I end up with the following exception when trying to switch to the tab:
'NSUnknownKeyException', reason: '[<UIViewController 0x451100> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key tableView.'
If I create a simple view based application with a Table View, everything works fine. I'll show the steps I go through below for both cases and hopefully someone can see what I'm doing wrong/differently that I don't realize.
Case 1:
In Xcode go to File...New Project...View Based Application, and name it Demo.
Open DemoViewController.h and add the following code in the appropriate two locations:
Open SecondViewController.m and add the following line:
Code:
@synthesize tableView;
Open SecondView.xib
Remove the label that says Second View
Select File's Owner and in the Inspector Identity tab change the Class to SecondViewController.
Drag a Table View into the view
Right click on the table view.
Drag from the dot beside New Referencing Outlet to File's Owner and select tableView.
Save everything and Build and Go.
The first view shows up fine. Click on the Second tab. The simulator crashes with the following stack trace on the console:
[Session started at 2008-08-29 08:10:45 -0600.]
Loading program into debugger…
Warning - No location found for "DatabaseSearchViewController.m:53"
GNU gdb 6.3.50-20050815 (Apple version gdb-960) (Sun May 18 18:38:33 UTC 2008)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin".warning: Unable to read symbols for "/System/Library/Frameworks/UIKit.framework/UIKit" (file not found).
warning: Unable to read symbols from "UIKit" (not yet mapped into memory).
Program loaded.
sharedlibrary apply-load-rules all
Attaching to program: `/Users/myusername/Library/Application Support/iPhone Simulator/User/Applications/662568B1-441A-4705-9003-0BF0D68D45C1/Demo2.app/Demo2', process 64174.
2008-08-29 08:10:50.011 Demo2[64174:20b] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIViewController 0x451100> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key tableView.'
2008-08-29 08:10:50.012 Demo2[64174:20b] Stack: (
2535018827,
2522071291,
2535017585,
2490358200,
2490356766,
2490899809,
818073927,
2534972549,
818068629,
818076920,
816648466,
816648934,
816688492,
816684429,
816177758,
818091155,
816177758,
816558114,
816559338,
816558227,
816177758,
816558114,
816559338,
816556080,
You are missing a few steps here. I think your main mistake is this:
"Right click on Classes...Add...New File...UIViewController subclass and name it SecondViewController."
You should be adding a new UITableViewController subclass instead. It has a tableView field already and it is automatically hooked up to the first table in the xib you don't need to hook it up. You do however need to connect the delegate and the data source to the file's owner in the xib, and of course connect the file owner's view to the table .
You are missing a few steps here. I think your main mistake is this:
"Right click on Classes...Add...New File...UIViewController subclass and name it SecondViewController."
You should be adding a new UITableViewController subclass instead. It has a tableView field already and it is automatically hooked up to the first table in the xib you don't need to hook it up. You do however need to connect the delegate and the data source to the file's owner in the xib, and of course connect the file owner's view to the table .
Thanks, this helped. I left the datasource and delegate out of the example because they were irrelevant to showing the exception. Following your example I can make things work, but I'm still not sure why the other way doesn't work. In my first example I am using a UIViewController and it works so why can't I do it in the second example?
More specifically, following your way only seems to work if the entire view is a table. I want a view in the second tab that has a search bar at the top, with a table taking the rest of the view and the only way IB lets me do that is if I am using a UIView, not a UITableView as the base view, and if I do that, I get errors saying the controller is expecting a UITableView. The only way to get rid of the errors is to switch the controller to a UIViewController (instead of UITableViewController as you suggest), which puts me right back at the spot I was in for my second demo.
I'm sure there's an easy way to do what I want, it just escapes me what it is. Is there a way to add another object to IB that I can connect my table view to? So I could have a UIViewController as the File's Owner, being the delegate and outlet for the search view, and then a second object that is a UITableViewController that is the delegate, datasource and outlet for the UITableView? Or am I trying to make things too complicated?
Well, I have things working the way I want them, but I'm not entirely sure why. After doing more research and looking into the TableSearch example, I found that it appeared they did exactly what I did in Case 2 of my original post, except including a UISearchBar as well. I repeated essentially what I did in Case 2, and this time it worked. I obviously did something different, but I'm not entirely sure what (and no, I did not use a UITableViewController anywhere).
Since I don't really have the time to keep repeatedly trying this over and over to find out what I did different, my test project instantly got promoted to a production project and I will deal with what was different the next time I need a search bar and table view together again.
In short:
Beside naming/locate the nib file, you must also set the class in the view inside the tab bar.
Fantastic find! I just tested this with my test case and it worked first try. In my vast fiddling I must have set this without realizing it to get my code working. I'm glad I can now consistently add tables to tab bars.
Hi indiekiduk, thanks. It's helpful for me.
I have created two tab with table view. But i got a problem to add a table item. In the first table view i added simply "Hello Universe" it's working. Then i added NSMutableArray on second table view. but now its not working*
FirstViewController.m - [cell setText:@"Hello Universe"] - it's working fine..
but if add NSArray to AppDelegate it's not working. did anything wrong in this??
but not sure how to access the navigation controller
to use the method pushViewController
thanks
sorry, totally new to iphone sdk =(
To access the navigation controller, you have to declare an IBOutlet for it in your controller class and connect it via IB the same way you connect any other outlet. Then you have direct access to it.
Hi indiekiduk, thanks. It's helpful for me.
I have created two tab with table view. But i got a problem to add a table item. In the first table view i added simply "Hello Universe" it's working. Then i added NSMutableArray on second table view. but now its not working*
FirstViewController.m - [cell setText:@"Hello Universe"] - it's working fine..
but if add NSArray to AppDelegate it's not working. did anything wrong in this??
You haven't provided a lot of information here but going from what you have posted, you need to have the array declared in your table view's data source, and set the cell text from the appropriate location in the array in the method
Actually, I played with it some more, and it appears you don't have to do any of the IBOutlet stuff, you can just use
Code:
[self navigationController]
to access the navigation controller containing the ViewController you are in.
The more I use it the more I hate using IB with the iPhone SDK. It is completely inconsistent in how things are done, with some requiring outlets and some not.
you are right, this works, any downside to doing this way?
what exactly does it mean when you call "self"?
is this similar to "this" in java? but then "this" in java only applies to the object you are on......what is "self" exactly referring to? the delegate?
Actually, I played with it some more, and it appears you don't have to do any of the IBOutlet stuff, you can just use
Code:
[self navigationController]
to access the navigation controller containing the ViewController you are in.
The more I use it the more I hate using IB with the iPhone SDK. It is completely inconsistent in how things are done, with some requiring outlets and some not.
My initial impression is also similar. But after [re]reading the official guides for the nth times, they give more sense every time (the guides are definitely NOT the easiest or best-seller reading materials).
navigationController is a property of UIViewController. The following is quoted from UIViewController reference (requires Apple ID):
navigationController
A parent or ancestor that is a navigation controller. (read-only)
Discussion
Only returns a navigation controller if the view controller is in its stack. This property is nil if a navigation controller cannot be found.
So, as long as the view controller is in the navigation controller's stack (being 'pushed' to the stack via pushViewController:animated: ), it will have a reference back to the navigation controller. Similar to this are tabBarController and parentViewController (it can be the controller that presents "self" as modal, or the navigation controller, or the tab bar controller, or nil). For these "parents", we don't need to create IBOutlets to refer to them.
Quote:
Originally Posted by rapidbunny
is this similar to "this" in java? but then "this" in java only applies to the object you are on......what is "self" exactly referring to? the delegate?
If you're using it inside the DetailedViewController class, then "self" is referring to its instance/object. DetailedViewController itself is a subclass of UIViewController. So, if it's been pushed to the navigation controller's stack previously, [self navigationController] (or self.navigationController) will refer to its "parent", i.e. the navigation controller.
"Beside naming/locate the nib file, you must also set the class in the view inside the tab bar.[/quote]"
I am extremely sorry for sounding naive. Could you please tell me menu wise steps for setting these values ? I am still scratching my head how to set this. I am getting exactly the same error using a navigation based app