I'm creating an application that first loads a settings screen which displays a series of text fields and labels asking the user for input. This is all working fine.
What I then want to do is once this data has been input, it comes up with the main application interface.
What is happening though is that when I'm telling the application delegate to load the main view, it says that the viewController isn't key value complaint for the key delegate.
The code I'm using to create the viewController is:
CustomViewController *viewController = [[CustomViewController alloc] initWithNibName:#"CustomViewController" bundle:nil];
self.window.rootViewController = viewController;
If anyone thinks that UIWindow doesn't have a rootViewController property, please check the documentation. That's what I did, and it does have one.
Any help with figuring this out would be greatly appreciated.
For those that like full debug info, this is what I get from xcode.
2011-06-18 15:03:15.474 Some App[15596:207] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<CustomViewController 0x53368b0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key delegate.'
Thanks,
Matt.
Most likely you try to use delegate somewhere in your xib file, but it doesn't exist in your CustomViewController class.
Check the connections in your nib file and remove the one that connects to the non existing delegate.
The rootViewController property was only recently introduced and might not be available on devices running an older version of iOS.
You want to have a UINavigationController as the root view controller of your application and subsequent pages you simply push onto it. If you don't want animation, then do animate:NO. If you don't need a navigation bar, then hide that as well.
It is generally preferable to use one of the existing container view controllers over swapping them out yourself.
Related
The line of code works fine on the iOS Simulator 6.0, but is crashing when I try to run it on my iPhone, also running iOS6.
[menuView addSubview:mvc.view];
Why is this happening, and how can I fix it?
This is the more complete version of the code:
SDMenuViewController *mvc = [[SDMenuViewController alloc] init];
[menuView addSubview:mvc.view];
And this is what it is crashing with:
2012-10-08 21:32:32.423 CrunchCalculator1-2[21019:907] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </var/mobile/Applications/EDD23933-CE20-4AFD-A2B1-CDD56AD658E8/CrunchCalculator1-2.app> (loaded)' with name 'SDNestedTableView''
*** First throw call stack:
(0x39cd03e7 0x35ece963 0x39cd0307 0x39ee0fd1 0x39ee05ff 0x39dd9031 0x39e0786d 0x39d63419 0xb20d9 0x39d63541 0x39da3d29 0x39d9fac5 0x39de1199 0xb17c5 0x39da4a71 0x39da45f5 0x39d9c803 0x39d44ce7 0x39d44775 0x39d441b7 0x31e145f7 0x31e14227 0x39ca53e7 0x39ca538b 0x39ca420f 0x39c1723d 0x39c170c9 0x39d9b43d 0x39d98289 0xb1523 0x3792fb20)
libc++abi.dylib: terminate called throwing an exception
Thanks!
I'm not quite sure how it worked on your simulator (when I tried it on mine, I got the crash you list in your original question). Anyway, you can fix it by looking at the following items:
The main problem is that the NIB was not included in the bundle. Add it to the project target's "Copy Bundle Resources", e.g.:
While you're looking at your "Copy Bundle Resources", you'll also want to include SDSubCell.xib, SDGroupCell.xib, and add all of those PNG files, too.
As an aside, while it doesn't apparently cause the crash, the "File Owner" base class in SDNestedTableView NIB refers to a class that doesn't exist anywhere in this project. That can't be good. Anyway, you probably want to change that to SDMenuViewController or SDNestedTableViewController;
It's a little unrelated to your crash, but as I look at the project, I see a worrying construct:
SDMenuViewController *mvc = [[SDMenuViewController alloc] initWithNibName:#"SDNestedTableView" bundle:nil];
[menuView addSubview:mvc.view];
You're creating a controller, grabbing its view, and either letting the view controller fall out of scope and be released (if you were using ARC) or leaking it (if not ARC).
I wasn't entirely sure from the original question whether you were doing addSubview as a way of transitioning to a new view (which is really bad practice) or whether you were doing view controller containment. As I look at the code, it appears you're doing the latter, though you're missing a few calls in your code. You might want to read up on view controller containment. And also check out that WWDC 2011 session 102.
Anyway, those two lines of code above with the view controller alloc/init and the subsequent addSubview will leak in your non-ARC project (and would crash it if you ever went to ARC) and your view hierarchy is out of sync with your view controller hierarchy. I'd suggest you might want:
SDMenuViewController *mvc = [[[SDMenuViewController alloc] initWithNibName:#"SDNestedTableView" bundle:nil] autorelease];
[self addChildViewController:mvc];
[mvc didMoveToParentViewController:self];
[menuView addSubview:mvc.view];
Note the autorelease on that first line.
View controller containment can be powerful, but you want to make sure you do some of this basic housekeeping.
One final update:
I notice that there are some bugs that are in this code. First, your use of currentSection in item:setSubItem:forRowAtIndexPath won't work. You're setting that based upon the last expandingItem. So, if you click on one of the main items before expanding either one, the program will crash. Probably best is to eliminate the currentSection variable altogether and in item:setSubItem:forRowAtIndexPath, use item.cellIndexPath.row rather than your variable currentSection.
Unfortunately, this fix leads to a more serious problem, there appears to be an iOS 6 bug in the SDNestedTable class, itself. If you run this on iOS 6 and you expand your all of your items, scroll to the bottom and then scroll back to the top, the program will crash because the cellIndexPath property of the SDGroupItem *item returned by item:setSubItem:forRowAtIndexPath can be deallocated! If you turn on zombies in iOS 6, you'll see cellIndexPath has been released. I went and downloaded the original version and see the same problem there. The problem appears to be that cellIndexPath in SDGroupCell is defined as an assign property (which means that if iOS determines it no longer needed the indexPath it created for its own purposes, it will be released even though SDGroupCell maintains an assign reference to this released object). Just change the cellIndexPath property of SDGroupCell from assign to retain, and this iOS 6 bug goes away. I've informed the developer of SDNestedTable of this issue, but this change to retain will fix the problem of the code crashing in iOS 6.
[Edit: The author of SDNestedTable agreed with my assessment of the issue, and he reports that this issue has been fixed the latest version. - Rob]
Best wishes.
You should probably use initWithNibName: insead of just init in the first line. Not sure regarding your specific issue, but certainly something to try.
It looks like you're trying to instantiate a nib called SDNestedTableView.nib and it isn't present. Is the nib included as a project member?
i am developing an application which would have many subviews like the flow of instagram and picyou kind of social networking apps the flow is image->detail image->any comment->username->following->username->image username->image->detail image->any comment->username->following->username->image username->damn this is infinite never stops.....
and never gets memory warning or crashed by memory issue...
i am using navigation controller but still after some time of navigation changing some viewcontrollers it gives me error like this *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Pushing the same view controller instance more than once is not supported (<ViewController: 0x6d97110>)'
i want to do same like this on pressing back you will also get all datas back. do you have any idea how to do like this.?
UINavigationController automatically supports this behavior you are describing. Memory efficient and potentially infinite.
Every time you want to go from one piece of your app to the next you just use code similar to this.
ViewController *vc = [[ViewController alloc] init];
//customize ViewController
[self.navigationController pushViewController:vc animated:YES];
So if you want to go from a photo to a photo detail view, you just push the photo detail view controller when the button is pressed. Even if your in a photo detail view controller already you can push another one from that class. Just make sure you create a separate instance. Judging by your error, I think that is your problem now.
I have also found it best to create a custom initializer for these kinds of view controllers. For a photo detail view use something like.
-(id)initWithPhoto:(Photo*)photo;
I am starting with iOS developments here and integrate Interface Builder within my projects.
I would have a question that is something I am experiencing right now, but I am not sure if in first place if I am doing it properly.
First Case
I have created all my UITableViewController inside IB and then changed the class to my custom CurrencyTableViewController. so for adding this inside my window.rootViewController at MainWindow_iPhone.xib I am just creating a variable straight away from inside the AppDelegate and calling the instance created in another .xib file. This works pretty well, but one of my concerns here is about memory management.
//Use the instance initiated by IB
CurrencyTableViewController *currencyTableViewController = [[[NSBundle mainBundle] loadNibNamed:#"CurrencyTableView" owner:nil options:nil] objectAtIndex:0];
So the question is: by using the method above to load instances created on IB are they released automatically after that? Or do I need to declare it somewhere else?
Second Case
This second case was an alternative trying to think on how to release the object, hence the creation of the instance instead the use of one instance already created. But unfortunately it seems to throw an error which says that I am not attaching the view to the controller. And this made me think that UITableViewController even being a subclass of UIViewController doesn't support the initWithNibName method...at least this is not declared on the documentation.
//Fails with: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "CurrencyTableView" nib but the view outlet was not set.'*** Call stack at first throw:
CurrencyTableViewController *currencyTableViewController = [[CurrencyTableViewController alloc] initWithNibName:#"CurrencyTableView" bundle:nil];
So, could one please confirm if it's not supported indeed and the only possible way to create an object and attach it to a nib file is if that element is UIViewController? if not, how the code bellow could work?
Thanks in advance for your support and time.
Regarding my first case:
It seems that when you create something from IB it is released automatically, no sure though.
Regarding the second case
It wasn't working because the controller was located on the nib as well so the first thing present inside a programmatically create instance of CurrencyTableViewController was another CurrencyTableViewController instead a view for that. so you can either remove the controller and just leave the tableView itself inside the nib or declare the instance as a representation of the nib element like the example on case one.
If someone have different alternatives please let me know.
So I have an app which runs fine on the simulator, but not on the actual device.
At runtime, it gives me the following error:
2010-12-05 19:58:32.006 Sports[4668:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableView isEqualToString:]: unrecognized selector sent to instance 0x800800'
A bit about the structure: I have a Tab Bar Controller, the first view being a UINavigationController.
The view in there is a UITableView. One thing that may or may not be related is that if I do #synthesize tableView; in the table view controller, the table stays blank on both simulator and phone (but does not crash).
If I take that out, it loads the correct data on the simulator, and crashes on the phone.
Where should delegate/dataSource be linked to in the Interface Builder? I tried linking it to "View" to "File's Owner", and making a new "ViewController" and none of those worked.
Both the delegate and dataSource should be linked to File's Owner, which is the view controller class that declares the table view as an IBOutlet; this should be the same view controller that owns the nib file. Additionally, that view controller should be implement the UITableViewDelegate and UITableViewDataSource protocols.
Add that #synthesize line back in, (unless you're subclassing UITableViewController, as pointed out by grahamparks in the comments!) make sure those connections are right, and, finally, make sure you've declared an IBOutlet for the table view, and connected that properly between your class and interface builder.
Found it!
Turns out that there wasn't really a problem with this at all. The problem was that the date field in my database, when run on my phone was always zero/nil.
Why? Because the NSDate object created never initialized and stayed at nil.
Why?
Because my phone is in 24 hour time and did not parse the am and pm properly.
Lessons learned!
Run your app with NSZombieEnabled set to yes. See http://www.cocoadev.com/index.pl?NSZombieEnabled for an explanation about it and how to set it. I think what you will find is that the app will now throw an exception in the simulator telling you that you are sending a message to an object that has been released.
Based on the error message you are receiving, I expect the culprit is a NSString or NSMutableString object. If it is an NSString then warning, that NSString could be shared by several different objects so figuring out where the extra release is might be hard.
Never fear though, Instruments helps tremendously in this regard. Here is a link that explains how to use Instruments to find out exactly where your object is being retained and released so you can track down which release is inappropriate. http://www.markj.net/iphone-memory-debug-nszombie/
Good luck!
This question already has answers here:
Xcode - How to fix 'NSUnknownKeyException', reason: … this class is not key value coding-compliant for the key X" error?
(79 answers)
Closed 7 years ago.
I'm writing my first iPhone app, so I haven't gotten around to figuring out much in the way of debugging.
Essentially my app displays an image and when touched plays a short sound.
When compiling and building the project in XCode, everything builds successfully, but when the app is run in the iPhone simulator, it crashes.
I get the following error:
Application Specific Information:
iPhone Simulator 1.0 (70), iPhone OS 2.0 (5A331)
*** Terminating app due to uncaught exception 'NSUnknownKeyException',
reason: '[<UIView 0x34efd0> setValue:forUndefinedKey:]: this class is not key value
coding-compliant for the key kramerImage.'
kramerImage here is the image I'm using for the background.
I'm not sure what NSUnknownKeyException means or why the class is not key value coding-compliant for the key.
(This isn't really iPhone specific - the same thing will happen in regular Cocoa).
NSUnknownKeyException is a common error when using Key-Value Coding to access a key that the object doesn't have.
The properties of most Cocoa objects can be accessing directly:
[#"hello world" length] // Objective-C 1.0
#"hello world".length // Objective-C 2.0
Or via Key-Value Coding:
[#"hello world" valueForKey:#"length"]
I would get an NSUnknownKeyException if I used the following line:
[#"hello world" valueForKey:#"purpleMonkeyDishwasher"]
because NSString does not have a property (key) called 'purpleMonkeyDishwasher'.
Something in your code is trying to set a value for the key 'kramerImage' on an UIView, which (apparently) doesn't support that key. If you're using Interface Builder, it might be something in your nib.
Find where 'kramerImage' is being used, and try to track it down from there.
Also when you rename a view, don't forget to delete the reference on File's Owner. It may also raise this error.
Here's one where you'll get this error - and how to fix it. I was getting it when loading a nib that just had a custom TableViewCell. I used IB to build a xib that just had the File's Owner, First Responder, and the TableViewCell. The TableViewCell just had 4 UILabels which matched up to a class with 4 IBOutlet UILabels called rootCell. I changed the class of the TableViewCell to be rootCell. It worked fine until a made a couple of changes and suddenly I was getting the setValue:forUndefinedKey: when I was just instantiating the class after loading it from a nib:
NSArray * nib = [[NSBundle mainBundle] loadNibNamed:#"rootCell-iPad" owner:self options:nil];
cell = [nib objectAtIndex:0];
It failed at the first line, when the nib was trying to load. After a while, I noticed that it was trying to match the IBOutlet Labels to the root controller, NOT the rootCell class! That was my tipoff. What I did wrong was to inadvertently change the File's Owner to rootCell class. When I changed it back to NSObject, then it didn't try to match up to the delegate (rootController) when loading. So, if you're doing the above, make File's Owner an NSObject, but make the UITableCell your desired class.
I had this situation and it turns out even after finding all instances of the variable and deleting them my app still crashed. Heres what happened... I created another instance of a variable from a textfield from my XIB into my viewController.h but I realized I didnt need it anymore and deleted it. It turns out my program saw that and kept trying to use it in the program so in the future if this happens to anywhere else just go into you XIB right-click on the button or textfield etc and delete any extra unused variables.
I had this same problem today. I didn't have the right class specified for the View Controller in my Navigation Controller. This will happen often if you fail to specify the correct class for your views in Interface Builder.
You'll also get invalid selector issues as well. Always check your Interface Builder classes and connections!
This is how i solved mine, in Interface builder right-click the View Controller, there should be an exclamation mark on the missing outlet or action method. Find and remove all the references and that solved it.
This happened because i deleted the action method in the .m file.
It seems you are doing
#interface MyFirstIphoneAppViewController : UIViewController<> {
UIImageView *InitialkramerImage;
}
#property(nonatomic,retain) IBOutlet UIImageView *InitialkramerImage;
Then after synthesizing that imageview, When you open "MyFirstIphoneAppViewController.xib" in Interface Builder, you are taking an Image View from Tool(menu)/Library den linking that outlet to the 'InitialkramerImage' from the Files Owner of "MyFirstIphoneAppViewController.xib". Then you saved the project. But after that you might change the name of the outlet variable "InitialkramerImage" to "kramerImage". So, after doing this
#interface MyFirstIphoneAppViewController : UIViewController<> {
UIImageView *kramerImage;
}
#property(nonatomic,retain) IBOutlet UIImageView *kramerImage;
and saving the project when you run it, There is no existance of the outlet of "InitialkramerImage" in the "MyFirstIphoneAppViewController.xib". So, when you run the project there will be no outlet referencing from Imageview to the 'kramerImage' and
"For displaying the view,
UIViewController will try to find the
outlet to "InitialkramerImage" which
is not existing."
So, It will throw the "NSUnknownKeyException".
You can check the missing outlet by
opening the nib(.xib) file then right
clicking on the 'Files Owner' of that.
If you have done this code somewhere else and had a zip/compressed file, try to extract it again. It may work I dont know why but I feel like it is an extraction issue.
or you can try to change the IBOutlet to kramerImage and bind it again in NIB.