views:

103

answers:

4

I just had a ridonkulous typo in my iPhone app, answered here.

Now I'm wondering about the @"..." notation.

why this works:

NSArray *someArray = [NSArray arrayWithObjects: @"Fairfield", nil];

and this does not (even though it compiles, it will throw an EXC_BAD_ACCESS):

NSArray *someArray = [NSArray arrayWithObjects: "@Fairfield", nil];

Edit:

Ok, so you guys have pointed out that I can't add a C string to an NSArray, because it's obviously not an object.

Now another question: Isn't this somewhat of an oversight? I mean, why does the "...WithObjects:" message specify a list of (id) instead of (NSObject *)?

+9  A: 

"@Fairfield" is a normal C string with an '@' character in it. @"Fairfield" is an Objective-C string (NSString on OS X) with no literal '@' in it.

You cannot add C strings to Cocoa collections.

Wevah
+2  A: 

"Fairfield" is a C string, @"Fairfield" is an Objective-C string.

@"Fairfield" is an object (NSString), so you can send it methods ([@"Fairfield" uppercaseString]) and add it to Objective-C arrays ([NSArray arrayWithObjects:@"Fairfield",nil]). You can only add objects to NSArrays.

On the other hand, "Fairfield" is a C string, and is generally not used in Cocoa. For the most part, you can get by with only using @"Fairfield"

igul222
+4  A: 

It accepts id rather than NSObject because all initialisers return id. All initialisers return id because subclasses would otherwise override the return type of their ancestors' initialisers.

For example, -[NSMutableString init] can't return NSMutableString * because it subclasses -[NSString init], which can't return NSString * because it overrides -[NSObject init].

Unfortunately, implicit type-casting between const char * and id is perfectly legit, so the compiler won't throw a warning, however a static analyser may be able to pick this sort of mishap up fairly easily.

dreamlax
Thank you for the explanation. Very helpful. Too bad the analyzer in XCode doesn't pick it up.
Jeff Meatball Yang
+1  A: 

The other reason that a number of things in Cocoa deal with id rather than NSObject* is because, unlike some other languages (say, Java and C#), where all objects in the language must inherit from some global base class, it's entirely possible to have objects that do not descend from NSObject (NSProxy being one example). It's not something you'd do often, but it is possible. The id type means "pointer to any Objective C instance".

Sixten Otto
Ahhhh... so this explains the reasoning for id. I had assumed that all NS* objects descended from NSObject.
Jeff Meatball Yang
In general, it's pretty safe to assume that they are. (Along with the non-NS* framework classes.) But it's not a rule that they *must* be.
Sixten Otto