[UICGColor length]: unrecognized selector sent to instance
Hi,
I'm trying to create an app that will display some entries from a plist. I'm creating a subclass of UITableViewController, and I'm setting the table data correctly.
However, when I try to scroll the table too much, my app crashes and I get this error:
[UICGColor length]: unrecognized selector sent to instance
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UICGColor length]: unrecognized selector sent to instance 0xd5ef60'
I don't even know what this means... lol. The table scrolls up and down fine, but if I push it up a lot, it dies. Why would it do this?
This is my entire class. Not really much here - I deleted the commented out autogenerated code.
The plist I'm using has data in the form of:
Dictionary:
Item - Array {String, Number}
So, there's a set of arrays stored in my dictionary, and the first item in the array is a string. I'm only trying to show one set of entries at a time (which is why the numberOfSections is always 1, and I have the currentSection variable).
I'm having this class called from another class. The view is popped in by the navigation controller from my root view. As I said, everything shows up just fine at first, but it will crap out on me if I scroll "too much".
Code:
@implementation SelectionTableViewController
@synthesize ItemsList;
@synthesize currentSection;
@synthesize toolbar;
- (void)viewDidLoad {
NSLog(@"SelectionTableViewController:viewDidLoad");
NSString *path = [[NSBundle mainBundle] pathForResource:@"ItemDataList" ofType:@"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.ItemsList = dict;
[dict release];
[super viewDidLoad];
//Initialize the toolbar
toolbar = [[UIToolbar alloc] init];
toolbar.barStyle = UIBarStyleDefault;
//Set the toolbar to fit the width of the app.
[toolbar sizeToFit];
//Caclulate the height of the toolbar
CGFloat toolbarHeight = [toolbar frame].size.height;
//Get the bounds of the parent view
CGRect rootViewBounds = self.parentViewController.view.bounds;
//Get the height of the parent view.
CGFloat rootViewHeight = CGRectGetHeight(rootViewBounds);
//Get the width of the parent view,
CGFloat rootViewWidth = CGRectGetWidth(rootViewBounds);
//Create a rectangle for the toolbar
CGRect rectArea = CGRectMake(0, rootViewHeight - toolbarHeight, rootViewWidth, toolbarHeight);
//Reposition and resize the receiver
[toolbar setFrame:rectArea];
//Create a button
UIBarButtonItem *infoButton = [[UIBarButtonItem alloc]
initWithTitle:@"Select" style:UIBarButtonItemStyleBordered target:self action:@selector(info_clicked:)];
[toolbar setItems:[NSArray arrayWithObjects:infoButton,nil]];
//Add the toolbar as a subview to the navigation controller.
[self.navigationController.view addSubview:toolbar];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)info_clicked:(id)sender {
NSLog(@"Info Clicked");
[toolbar setHidden:YES];
[[self navigationController] popViewControllerAnimated:YES];
}
- (void)viewWillAppear:(BOOL)animated {
[toolbar setHidden:NO];
[self.tableView reloadData];
[super viewWillAppear:animated];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[ItemsList objectForKey:currentSection] count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
int row = [indexPath row];
NSString *cellLabel = [[[ItemsList objectForKey:currentSection] objectAtIndex:row] objectAtIndex:0];
cell.textLabel.text = cellLabel;
[cellLabel release];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
// AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
// [self.navigationController pushViewController:anotherViewController];
// [anotherViewController release];
// [tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)dealloc {
[ItemsList release];
[super dealloc];
}
@end
However, when I try to scroll the table too much, my app crashes and I get this error:
[UICGColor length]: unrecognized selector sent to instance
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UICGColor length]: unrecognized selector sent to instance 0xd5ef60'
Look in the stack trace and find out what line it's crashing on. It sounds like somethings indexing outside an array bounds but hard to tell without running the code
Once your string gets released it's being replaced in memory by something else; and that other object is catching messages intended for your string and choking on them.
Once your string gets released it's being replaced in memory by something else; and that other object is catching messages intended for your string and choking on them.
Doh!! Ok - I'll take that release out when I get home tonight and give it a whirl. I'm still relatively new to Objective C, so I'm not entirely surprised I'm doing something like that. lol.
Thanks smasher!
pwnified: When I was looking through the stack trace, it was following all kinds of functions I've never seen, and the only one that I could click on and see where it was in my code, was at the bottom where it called the application main.. lol. I really wasn't sure what to make of it.
Doh!! Ok - I'll take that release out when I get home tonight and give it a whirl. I'm still relatively new to Objective C, so I'm not entirely surprised I'm doing something like that. lol.
Thanks smasher!
pwnified: When I was looking through the stack trace, it was following all kinds of functions I've never seen, and the only one that I could click on and see where it was in my code, was at the bottom where it called the application main.. lol. I really wasn't sure what to make of it.
Don't feel bad - it's a particularly unhelpful error message, and it sounds like a particularly unhelpful stack trace too. Good luck.
pwnified: When I was looking through the stack trace, it was following all kinds of functions I've never seen, and the only one that I could click on and see where it was in my code, was at the bottom where it called the application main.. lol. I really wasn't sure what to make of it.
Yeah when it's a memory problem the stack doesn't help much as it usually fails deep inside system calls.
One thing you could do next time, is to enable zombies to help debug it. Right click your executable in xcode (under Executables in the Overview), select Get Info, select Arguments, and under "Veriables to be set in the environment" create a variable called "NSZombieEnabled" and set the value to YES.
Now when running your app, all deallocations get moved to a zombie pool, and it'll throw an exception if the object is referenced with a readable stack. Dont forget to uncheck the NSZombieEnabled when you're done
Yeah when it's a memory problem the stack doesn't help much as it usually fails deep inside system calls.
One thing you could do next time, is to enable zombies to help debug it. Right click your executable in xcode (under Executables in the Overview), select Get Info, select Arguments, and under "Veriables to be set in the environment" create a variable called "NSZombieEnabled" and set the value to YES.
Now when running your app, all deallocations get moved to a zombie pool, and it'll throw an exception if the object is referenced with a readable stack. Dont forget to uncheck the NSZombieEnabled when you're done
Cool.. thanks for the tip! zombies are always cool to have around.
Ok - I have another question that's marginally related to my previous question. I was trying something else out, with using a xib with a tableview and toolbar on it already (I was having some trouble with the toolbar being over the bottom row of the table).
I'm trying to reference the table in code to reload the data. If it was a subclass of UITableViewController, I know I could do self.tableview... but when it's a UIViewController, how do I access the tableview?
Hey everyone, I am having a similar problem, and have not been able to figure it out yet. Basically, I have a UIButton called optionsButton that is a @property of my RootViewController class, and it is @synthesized in my RootViewController implementation. I have a function that when the optionsButton is clicked, creates a new view and should removeFromSuperview anything in the current view (which is only the optionsButton).
The new view that is created will use the same selector to perform basically the opposite function. It will remove itself from the current view and then replace the optionsButton. Here is the code from this function:
Code:
- (IBAction)gotoOptions {
if (optionsView.superview != nil) {
// remove options view
[self.optionsView removeFromSuperview];
// load the buttons, etc.
[self.view addSubview:optionsButton];
} else {
// remove the buttons from the view
[self.optionsButton removeFromSuperview];
// load the options view
UIView *aView = [[UIView alloc] initWithFrame: CGRectMake(20, 105, 280, 330)];
aView.backgroundColor = [UIColor viewFlipsideBackgroundColor];
// add a button to the view
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setFrame:CGRectMake(5, 5, 110, 30)];
[aButton setTitle:@"Main Menu" forState:UIControlStateNormal];
[aButton addTarget:self action:@selector(gotoOptions) forControlEvents:UIControlEventTouchUpInside];
[aView addSubview:aButton];
self.optionsView = aView;
// display the options view
[self.view insertSubview:optionsView aboveSubview:self.view];
}
}
I am not releasing the optionsButton, simply removing it from superview. Can anyone please point me in the right direction? The code works fine for removing the button, it crashes when trying to add the button back in with this error:
Code:
2009-08-12 12:35:32.745 XPlode[5499:20b] *** -[NSCFSet superview]: unrecognized selector sent to instance 0x52a6b0
It's a little hard to follow because your method "goToOptions" clearly does two different things at different times - sometimes it shows the options buttons, and sometimes it removes options and shows the options button?
Either way, at some point optionsView or optionsButton is pointing to something that is not a UIView. It probably happens when the object it points to gets released too many times. Is the optionsButton property set to retain?
I can't see the error in what you posted. How do you create the optionsButton, though? If you create it with buttonWithType and set the variable directly (without "self.optionsButton") then there is nothing retaining it, and it will get dealloc'd when it is removed from the superview.
It's a little hard to follow because your method "goToOptions" clearly does two different things at different times - sometimes it shows the options buttons, and sometimes it removes options and shows the options button?
Either way, at some point optionsView or optionsButton is pointing to something that is not a UIView. It probably happens when the object it points to gets released too many times. Is the optionsButton property set to retain?
I can't see the error in what you posted. How do you create the optionsButton, though? If you create it with buttonWithType and set the variable directly (without "self.optionsButton") then there is nothing retaining it, and it will get dealloc'd when it is removed from the superview.
Thanks smasher, you hit the nail right on the head. I was releasing the button, even though I was creating it with buttonWithType:.