views:

250

answers:

1
+1  Q: 

Cocoa Webkit bug?

I have some code that gets the URL from an array and stores it as a string then uses that string to load up the URL.

NSString *first = [urls objectAtIndex:[sender clickedRow]];
NSLog(@"%@", first);
[[webview mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:first]]];

However, when I run this I get this error:

-[NSURL length]: unrecognized selector sent to instance 0x164dc0

The link in this case is http://www.digg.com

I know that the bug is in the line

NSString *first = [urls objectAtIndex:[sender clickedRow]];

because I tried setting the string's value directly to the URL instead of the array and it worked.

+5  A: 

However, when I run this I get this error:

-[NSURL length]: unrecognized selector sent to instance 0x164dc0

First off, that's an exception, not an error.

When you get a message like this, read what it says:

-[NSURL

The object you sent this message to was an NSURL object.

length]:

The selector of the message was length.

Now, why would you send a length message to an NSURL object? You wouldn't, and you didn't do so yourself. Something else did.

But you would send a length message to a string object. So, you have an NSURL object, and you passed it somewhere that expected a string.

There's only one passage in the code you showed:

[NSURL URLWithString:first]

The exception tells you that first is already an NSURL; it is not a string. You do not need to create an NSURL from it, since it already is one, and trying to treat it as a string in any way will cause an exception.

You may be about to object to my claim on the grounds of this previous line:

NSString *first = [urls objectAtIndex:[sender clickedRow]];

Your objection would be that the declaration clearly says that first is a pointer to an NSString, so I must be wrong.

But that is not so. You declared first as a pointer to an NSString. That is to say, you told the compiler that the variable first would hold a pointer to an NSString.

But then you put a pointer to an NSURL into the variable.

In many cases, the compiler would warn you that you have lied to it, but it didn't in this case because the object came through objectAtIndex:, which returns id; thus, the compiler doesn't know what type of object you're putting into the variable. The compiler, assuming that you told the truth and really are putting an NSString here, does not warn for this initialization.

But you're not. The object is an NSURL, as you found out at run time.

The fix is two-fold:

  1. Restore truth to the declaration, by declaring the variable as NSURL *, not NSString *.
  2. Don't attempt to create an NSURL here, because you already have one.
Peter Hosey
That's a great answer.
Rob Keniger
That is an awesome answer (wish I could vote it up twice)I tried making it an NSURL, but the same thing happened. Same NSURL length. When compiling (with the NSURL) I get the warning "Incompatible Obj-C types 'struct NSURL*', expected 'struct NSString*' ... of 'URLWithString:' from distinct Obj-C type"
Matt S.
Just changing the variable declaration isn't enough. You also need to not pass the NSURL object to places that want an NSString, like `[NSURL URLWithString:]`. As I said, you already have an NSURL, so you don't need to create one and trying to do so will cause the exception.
Peter Hosey
If you've already fixed that and are still getting the exception, then run your app in the debugger and look at the stack trace, because you have made the same mistake (possibly with a different method) someplace else.
Peter Hosey
Yep. That I did. Thanks a bunch for your help!!!
Matt S.