views:

1434

answers:

9

I get a crazy error and I am unable to see why it happens. I have made a simple app that uses a TabBar to navigate 3 views. I created everything and added one UIImageView to each of the 3 ViewControllers that the TabBar manages. Everything works fine. In the app you are able to navigate the 3 views and see the 3 images.

Now I add one UIButton (or any other component) to the 1st ViewController. I add it in the NIB and in my code I do the usual:

IBOutlet UIButton *btn;
@property (nonatomic, retain) IBOutlet UIButton *btn;

@synthesize btn;
[btn release];

and connect the UIButton in my NIB to the "btn". Now the app crashes as soon as the TabBar tries to show this view (which is imediately after it launches) giving me a:

2009-08-24 16:52:25.164 AppName[2249:207] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key btn.'

I tried restarting the SDK, my computer, building for 2.2.1, 3.0, for simulator, for device, cleaning all targets, etc but the problem remains. I am sure it has something to do with the UITabBarController. I just can't see what.

A: 

I'm presuming your 4 lines of code are all in the right place? Worth double-checking, as it looks like the compiler is thinking you intend something different for btn.

So, worth double checking that your 4 lines appear as follows:

// in your myController.h file

@interface myController:UIViewController {    
IBOutlet UIButton *btn;
}

@property (nonatomic, retain) IBOutlet UIButton *btn;
@end

and

// in your myController.m file

@implementation myController    
@synthesize btn;

- (void)dealloc {
   [btn release];
   [super dealloc];
}

@end

I expect you've put all the bits in the correct place, but like I said it's just worth double-checking!

h4xxr
Yes, it always is. Unfortunately for me they are all in the right place... It's a really strange problem. Just wiring up an Outlet crashes the app.
Dimitris
So if the button's on the view but the IBOutlet doesn't exist, does it still crash? How about if the IBOutlet exists but the button doesn't?
h4xxr
If the code is there but the button is not in IB the it works. Also if the button is in the NIB but there is no code, it works...
Dimitris
It's like the code of the ViewController of that class is never run... It never gets in the ViewDidLoad method... But still I have set the File's Owner in the NIB to be of that class. At least it starts to look like a trivial mistake on my part now. Just need to find it.
Dimitris
(for what I'm talking about above I have removed the button from the NIB and I am creating it by code in the class. So the app works again and I can navigate all the views. However that doesnt happen since the ViewDidLoad method is never run)
Dimitris
No. I still can't find what causes it... :S
Dimitris
+1  A: 

You will get that error when you connect a control to an outlet that doesn't exist.

The most important part of your error message was left out (because it was wrapped in angle-brackets):

reason: [<classname> setValue:forUndefinedKey:

classname is the class you, perhaps inadvertently, hooked up the button to in Interface Builder. It doesn't have a btn outlet.

Darren
I think you are spot on. The problem is I can't seem to set the loaded NIB to be of that specific class (and therefore inherit its properties). I set it's File's Owner class to (let's say) "ViewOneController" but still the "ViewDidLoad" of the "ViewOneController" is never called. Even though the contents of the NIB show on the screen. I think I will try to build the app from scratch tomorrow 'cause it feels like I've done everything right... I'd be glad to see someone proving me wrong of course :)
Dimitris
You'll want to check both awakeFromNib and viewDidLoad methods. I think there are cases where one is called instead of the other.But it sounds like you're passing in the wrong object as the nib's owner when you load the nib. Regardless of what you type of class specify in Interface Builder, you can pass any type of object you want as the owner of the nib. If that object's interface doesn't match what the nib expects you'll get the error you're describing.
Darren
+1  A: 

The problem seemed to have been caused by the UITabBarController in my MainWindow NIB. I couldn't fix it so I deleted the UITabBarController from the NIB and created it in code in my AppDelegate class. Then I set all me other classes to "initWithNib" and I can now set IBOutlets in them just fine.

Dimitris
A: 

I recently encountered this exact error, and found that just doing a Clean All targets fixed the problem. Might be as simple as that.

DanM
I don't remember now, but I am sure i've tried that. I always do when something unexpected happens..
Dimitris
+1  A: 

I had a similar problem. It was because the UIViewController for the tab was not set to the specific subclass of UIViewController I had created.

If you look at the .xib in IB you'll see something like this:

  **Name**                **Type**
  File's Owner        UIApplication
  First Responder     UIResponder
  Tab Bar Controller  UITabBarController
     Tab Bar          UITabBar
     View Controller  UIViewController
     View Controller  UIViewController
     View Controller  UIViewController

The View Controllers under the tab bar controller will default to a basic UIViewController. You need to change their class to your subclassed view controller in order for them to load and connect to your outlets correctly:

  **Name**                **Type**
  File's Owner        UIApplication
  First Responder     UIResponder
  Tab Bar Controller  UITabBarController
     Tab Bar          UITabBar
     FirstTab View Controller  MyFirstTabController
     SecondTab View Controller MySecondTabController
     ThirdTab View Controller  MyThirdTabController

Then when the tab creates the controller for your tab it will be creating the correct class. Note, this is probably why your viewDidLoad method is not called

Andy Johns
I can't remember right now of course, but changing the class of the UIViewController seems like the 1st think I would do. Anyway, thanks for sharing more information :)
Dimitris
A: 

I had this problem today. Cause: I had defined IBOutlet in my delegate, and connected it. Later on I removed it from code file. However, the reference was still active in XIB file. It was grayed out. Removing the reference in XIB helped.

I was doing something else so I thought the problem was in the new component I added, not realizing it was caused by this.

Simo Salminen
A: 

Thanks Andy Johns, not having set the specific viewcontroller class was "my" error. I don't remember that I have set the actual class for other tabs in the tabcontroller, so I was about to get totally mad with this one. I guess this is the price to pay for "easy" assembling an interface with IB...

Rick
A: 

Thanks Andy! That was my issue.

A: 

Andy Johns' answer fixed my problem. I hadn't even thought of that, and I was completely confused as to why the simplest things weren't working. Thank You!

art