views:

1209

answers:

2

Hello. I am getting an error in my console:

2009-05-30 20:17:05.801 ChuckFacts[1029:20b] *** -[Joke isEqualToString:]: unrecognized selector sent to instance 0x52e2f0

Here is my code that I believe the error is coming from:

- (UITableViewCell *)tableView:(UITableView *)tableView 
     cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Joke";  
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) { 
 [[NSBundle mainBundle] loadNibNamed:@"TableCell" owner:self options:nil]; 
 cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero 
           reuseIdentifier:CellIdentifier] autorelease];
 cell = tableCell;
}

NSString *jokeText = [jokes objectAtIndex:indexPath.row];
UILabel *jokeTextLabel = (UILabel*) [cell viewWithTag:1];
jokeTextLabel.text = jokeText; 
NSString *dateText = formattedDateString;
UILabel *dateTextLabel = (UILabel*) [cell viewWithTag:2];
dateTextLabel.text = dateText;
[self todaysDate];
return cell;
}

"jokes" is an array full of jokes, incase you needed to know

Why is that error coming in?

Also, do you see the part of the error that says:

sent to instance 0x52e2f0

How can I determine what "0x52e2f0" is so it would be easier to find the problem next time?

+2  A: 

By "an array full of jokes", you apparently mean "an array full of classes of type Joke". You can't assign a Joke object to a UILabel's text property—it takes NSString only.

(Cocoa isn't like Java or C++, where any object can be coerced to a string automatically through some .toString() method. Generally the framework asks for NSStrings explicitly when it wants a string.)

Here's what's happening: you're assigning a Joke object to the text property. Cocoa allows you to play fast and loose with types like this, without even a warning in this case since it's implicitly understood to be an NSString (the id type will silently become whatever type you're assigning it to). But when it tries to call isEqualToString: (an NSString method) on a Joke object, of course it fails.

You need to assign the joke's text to the label instead.

As for how to identify the object: you can issue the po 0x52e2f0 command in the debugger, which usually works if memory isn't completely borked. It'll print an Objective-C representation of the object at that address.

Adam Ernst
Actually, there's no (relevant) typecast in this case: the NSArray message objectAtIndex: returns 'id', which is coercible to any pointer type without a warning.
Adam Rosenfield
Indeed you're right. Corrected.
Adam Ernst
You actually can get a string representation of any object using the -description method. The default implementation would just return something like <Joke: [address]> unless you overrode it though.
Jim Dovey
Right. But unlike Java, there is no automatic coercion or automatic calling of description, except for NSLog.
Adam Ernst
+12  A: 

Why is that error coming in?

Because you're sending isEqualToString: to a Joke object, and your Joke objects don't respond to isEqualToString:.

You're probably not intentionally sending that message to your Joke objects; instead, you're passing or returning Joke objects to something that is expecting NSString objects.

You say that jokes is an “array of full of jokes”. Yet, in your code, you do this:

NSString *jokeText = [jokes objectAtIndex:indexPath.row];
UILabel *jokeTextLabel = (UILabel*) [cell viewWithTag:1];
jokeTextLabel.text = jokeText;

Going by the exception, I'm guessing that by “array full of jokes”, you meant “array of Joke objects”.

Putting a Joke object into an NSString *variable does not turn the Joke object into an NSString. All you're doing is telling the compiler that the variable contains an NSString, then putting a Joke into it instead. I call this “lying to the compiler”.

The first step in fixing this is to remove the lie and restore truth in its place:

Joke *joke = [jokes objectAtIndex:indexPath.row];

If you compile immediately after doing this, you'll notice that the compiler has started giving you a warning a couple of lines later:

jokeTextLabel.text = jokeText;

warning: passing argument 1 of ‘setText:’ from distinct Objective-C type

It's right, of course. Jokes still aren't NSStrings. Now that you're honest about the variable's type, the compiler can catch this for you.

The actual fix comes when you ask the Joke object for its text (I assume that it has a property for this, and that the value of that property is an NSString) and give that to the jokeTextLabel.text setter.

How can I determine what "0x52e2f0" is so it would be easier to find the problem next time?

In Xcode's Breakpoints window, set a breakpoint on objc_exception_throw. Then run your program. When the exception happens, the debugger will stop your program, and the Debugger window will open. Then, type po 0x52e2f0 into the Debugger Console. (po stands for “print object”.)

This works for Mac apps; I'm assuming it'd also work for iPhone apps.

Peter Hosey
Another excellent answer from you, Peter.
Abizern