Often in objective C, you know an object is a kind of particular class, so you cast it into that class to continue using it:
NSObject *object;
NSString *string = (NSString *)object;
But, this has bothered me for some time - is there any advantage to writing out "NSString *" in that cast as opposed to the shorter (id):
NSObject *object;
NSString *string = (id)object;
I typically favor verbose Objective-C because the language is designed for readability, but I can't figure out any advantage of being verbose in this case.
Anything you can do to give the compiler more precise and accurate information about the types in play, the more the compiler can validate your code. The id type basically means *this thing responds to any method I've ever seen declared` to the compiler wherein a specific cast narrows it to only the methods that class supports.
In general, casts are to be avoided. They generally indicate poor architecture. Not always, though, as they are oft unavoidable when dynamically generating UI or parsing JSON.
In that case, a construct that boils down to this is oft helpful:
NSObject *object;
NSAssert((!object) || [object isKindOfClass:[NSString class]]);
NSString *string = (NSString *)object;
That forces verification of the I know better than the compiler to runtime. (And, yes, it explicitly allows nil to pass through in this case.... your specific needs may vary.)
I think that the best way is not using down-casting at all by developing more thought-out architecture.
Constructions like this NSString *string = (NSString *)object; simply hide compiler warning and don't make any run-time casting.
But there are some situations when compiler can't know what kind of object is returned by method. For example: [NSDictionary valueForKey:] returns object of id type that is reference to object of any class. It is so because NSDictionary could contain any objects of any class and Objective C doesn't support templates where you could provide class of objects that collection will contain due initialisation.
In such situations usually used constructions like this:
id object = dictionary[key];
NSString *string = object;
Update:
However if consider situation when method returns object of kind NSObject that is really NSString then for compiler it doesn't matter what kind of casting you use: (id) or (NSString *) . But logically it's better to use (NSString *) as it shows kind of object that you expect. I mean that it is more clear for person who will read your code.
Related
I am looking at a code base which is full of
NSString *const kTabChart = #"Charts";
NSString *const kTabNews = #"News";
and then
setSelectedTab:(NSString *)title;
...
someThingElse:(NSString *)title;
So these weak-typed NSString go far and all the way around the code and this just irritates my eyes. Enums would be better to some extent, but enums would not have the names available programmatically and I do not want to define all unrelated tab names from different views within the same enum {}
I wonder if there is a better way? I am dreaming of a way to make it something like
#interface PageTitle:NSSting;
PageTitle kTabChart = /some kind of initializer with #"Chart"/;
PageTitle kTabNews = /some kind of initializer with #"News"/;
I suspect that this would not play well with the whole "not a compile-time constant" constraint, but I wonder if there are tricks/patters/hacks to define constants of my own class type.
You should use NS_TYPED_ENUM as this makes it into a rawVlaue. More info https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/grouping_related_objective-c_constants
Sure, just think subclassing. First our class, which is a subclass of NSString:
#interface StringConstants : NSString
extern StringConstants * const kOptionApple;
extern StringConstants * const kOptionBlackberry;
#end
So we've defined StringConstants and a couple of global constants for it. To implement the class without any warnings just requires some casting:
#implementation StringConstants
StringConstants * const kOptionApple = (StringConstants *)#"Apple";
StringConstants * const kOptionBlackberry = (StringConstants *)#"Blackberry";
#end
And there is our set of constants. Let's test it:
- (void) printMe:(StringConstants *)string
{
NSLog(#"string: %#", string);
}
- (void) test
{
[self printMe:kOptionApple]; // Code completion offers the constants
[self printMe:#"Rhubarb"]; // Warning: Incompatible pointer types
[self printMe:(StringConstants *)#"Custard"]; // OK
}
You only get a warning, the code will run, as with other similar type errors.
You can of course repeat the pattern and produce one "class" per set of strings.
HTH
Addendum: It Is Safe (Trust Me For Now) and the Weak Enum
Concern has been raised in the comments that the above code is essentially dangerous, it is not. However in the general case the concerns raised are valid, it is safe here by design.
Note: This is being typed directly into SO. Please forgive the inevitable spelling & grammar errors, and the probable lack of good presentation, well defined explanatory arc, missing bits, redundant bits etc.
First let's add the missing comments to the above code, start with the implementation:
// The following *downcasts* strings to be StringConstants, code that
// does this should only appear in this implementation file. Use in
// other circumstances would effectively increase the number of "enum"
// values in the set, which rather defeats the purpose of this class!
//
// In general downcasting should only be performed after type checks to
// make sure it is safe. In this particular case *by design* it is safe.
StringConstants * const kOptionApple = (StringConstants *)#"Apple";
There are two different issues here
Is it safe at all - yes by design, trust me (for now); and
The addition of additional "enum" values
The second is covered by the second missing comment in the test code:
[self printMe:(StringConstants *)#"Custard"]; // OK :-( - go ahead, graft
// in a new value and shoot
// yourself in the foot if
// you must ;-)
The weak enum
Dealing with the second issue first, unsurprisingly this "enum" isn't bulletproof - you can add additional values on the fly. Why unsurprising? Because you can do it in (Objective-)C as well, not only is the language not strongly typed the enum types are the weakest of the lot. Consider:
typedef enum { kApple, kBlackberry } PieOptions;
How many valid values of PieOptions are there? Using Xcode/Clang: 2^32, not 2. The following is perfectly valid:
PieOptions po = (PieOptions)42;
Now while you should not write such obviously wrong code the need to convert between integers and enum values is common - e.g. when storing "enum" values in the tag field of UI controls - and thus the room for errors. C-style enumerations have to be used with discipline, and used that way are a good aid to program correctness and readability.
In the same way StringConstants must be used with discipline, no casting arbitrary strings - the equivalent of the 42 example above - and with discipline they have similar advantages and disadvantages to standard enumerations.
With the simple discipline of not casting arbitrary strings to StringConstants; something which is allowed only in the StringConstants implementation itself; this type gives you a completely safe "enumeration of string values" with compile-time warnings if used incorrectly.
And if you trust me you can stop reading now...
Addendum: Digging Deeper (Just Curious or We Don't Trust You)
To understand why StringConstants is completely safe (even adding additional values isn't really unsafe, though it may of course cause a program logic failure) we'll go through a number of issues about the nature of object-oriented programming, dynamic typing and Objective-C. SOme of what follows isn't strictly necessary to understand why StringConstants is safe, but you're someone with an inquiring mind aren't you?
Object reference casts don't do anything at runtime
A cast from one object reference type to another is a compile-time statement that the reference should be treated as being to an object of the destination type. It has no effect on the actual referenced object at runtime - that object has an actual type and it doesn't change. In the object-oriented model upcasting, going from a class to one of its superclasses, is always safe, downcasting, going in the reverse direction, may not (not is not) be safe. For this reason downcasting should be protected by tests in the cases it may be unsafe. For example given:
NSArray *one = #[ #{ #"this": #"is", #"a" : #"dictionary" } ];
The code:
NSUInteger len = [one.firstObject length]; // error, meant count, but NO compiler help at all -> runtime error
will fail at runtime. The result type of firstObject is id, which means any object type, and the compiler will let you call any method on references typed as id. The mistakes here are to not check the array bounds and that the retrieved reference is in fact a dictionary. A more bulletproof approach is:
if (one.count > 0)
{
id first = one.firstObject;
if ([first isKindOfClass:[NSDictionary class]])
{
NSDictionary *firstDict = first; // *downcast* to improve compile time checking
NSLog(#"The count of the first item is %lu", firstDict.count);
}
else
NSLog(#"The first item is not a dictionary");
}
else
NSLog(#"The array his empty");
The (invisible) cast is perfectly safe, protected as it is by the isKindOf: test. Accidentally type firstDict.length in the above code fragment and you will get a compile-time error.
However you only need to do this if the downcast might be invalid, if it cannot be invalid no tests are required.
Why can you call any method on references types as id?
This is where Objective-C's dynamic runtime message lookup comes into play. The compiler checks, to the best of its ability, for type errors at compile-time. Then at runtime another check is made - does the referenced object support the called method? If it does not a runtime error is generated - as occurs with the length example above. When an object reference is typed as id this is an instruction to the compiler to perform no compile-time check at all and leave it all to the runtime checks.
The runtime check is not checking the type of the referenced object, but instead whether it supports the requested method, which leads us to...
Ducks, NSProxy, Inheritance, et. al.
Ducks?!
In dynamic typing there is a saying:
If it looks like a duck, swims like a duck, and quacks like a duck, then it is a duck.
In Objective-C terms this means that at runtime if a referenced object supports the set of methods of type A then it is effectively an object of type A regardless of what it real type is.
This feature is used in many places in Objective-C, a notable example is NSProxy:
NSProxy is an abstract superclass defining an API for objects that act as stand-ins for other objects or for objects that don’t exist yet. Typically, a message to a proxy is forwarded to the real object or causes the proxy to load (or transform itself into) the real object. Subclasses of NSProxy can be used to implement transparent distributed messaging (for example, NSDistantObject) or for lazy instantiation of objects that are expensive to create.
With NSProxy you may think you have, say, an NSDictionary - something which "looks, swims and quacks" like an dictionary - but in fact you've not got one at all. The important points are:
It does not matter; and
It is perfectly safe (modulo coding errors if course)
You can view this ability to substitute one object for another as a generalisation of inheritance - with the later you can always use a subclass instance in lieu of a superclass one, with the former you can use any object in place of another as long as it "looks, swims and quacks" like the object it is standing in for.
We've actually gone further than we need, ducks are not really required to understand StringConstants, so let's get on:
When is a string an instance of NSString?
Probably never...
NSString is implemented by a class cluster - a collection of classes which all respond to the same set of methods that NSString does, i.e. they all quack like NSString. Now these classes may be subclasses of NSString, but in Objective-C there is no actual need for them to be.
Furthermore if you think you have an instance of NSString you may actually have an instance of NSProxy... But it does not matter. (Well it might impact performance, but it doesn't impact safety or correctness.)
StringConstants is a subclass of NSString, so it certainly is an NSString, except that NSString instances probably don't exist - every string is actually an instance of some other class from the cluster, which may or may not itself be a subclass of NSString. But it does not matter!
As long as instances of StringConstants quack like NSStrings should then they are NSStrings - and all the instances we have defined in the implementation do that as they are strings (of some type, probably __NSCFConstantString).
Which leaves us with the question is the defining of the StringConstants constants sound? Which is the same question as:
When is Downcasting Known To Be Always Safe?
First an example of when it is not:
If you have a referenced typed as NSDictionary * then it is not known to be safe to cast it to NSMutableDictionary * without first testing whether the reference is to an mutable dictionary.
The compiler will always let you do the cast, you can then at compile-time make calls to mutating methods without error, but at run-time there will be errors. In this case you must test before casting.
Note that the standard test, isKindOf:, is effectively conservative due to all those ducks. You may actually have a reference to an object which quacks like an NSMutableDictionary but is not an instance of it - so the cast would be safe but the test will fail.
What makes this cast unsafe in general?
Simple, it is not known whether the reference object responds to the methods that an NSMutableDictionary does...
Ergo, if you did know that the reference must respond to all the methods of the type you are casting to then the cast is always safe and no test is required.
So how do you know the reference must respond to all the methods of the target type?
Well one case is straightforward: If you have a reference typed as T you can it to a reference of type S safely without any checks whatsever if:
S is a subclass of T - so it quacks like a T; and
S adds no instance state (variables) to T; and
S adds no instance behaviour (new methods, overrides etc.) to T; and
S overrides no class behaviour
S may add class new class methods (not overrides) and global variables/constants without violating these requirements.
In other words S is defined as:
#interface S : T
// zero or more new class methods
// zero or more global variables or constants
#end
#implementation S
// implementation of any added class methods, etc.
#end
And We Made It...
Or did we, anybody still reading?
StringConstants is by design constructed so that string instances can be cast to it. This should only be done in the implementation, sneaking in additional "enum" constants elsewhere goes against the purpose of this class.
It is safe, indeed its not even scary :-)
No actual instances of StringConstants are ever created, each constant is an instance of some string class safely at compile-time masquerading as a StringConstants instance.
It provides compile-time checking that a string constant is from a pre-determined set of values, it is effectively a "string valued enumeration".
Yet Another Addendum: Enforcing Discipline
You cannot completely automatically enforce the discipline required to code safely in Objective-C.
In particular you cannot have the compiler prevent programmers from casting arbitrary integer values into enum types. Indeed, due to uses such as the tag fields of UI controls, such casts need to be allowed in certain circumstances - they cannot be totally outlawed.
In the case of StringConstants we cannot have the compiler prevent the cast from a string everywhere except in the implementation of the class itself, just as with enum extra "enum" literals can be grafted in. This rule requires discipline.
However if discipline is lacking the compiler can assist with preventing all the ways, other than casting, that can be used to create NSString values and hence StringConstant values as it is a subclass. In other words all the initX, stringX etc. variations can be marked as unusable on StringConstant. This is done by simply listing them in the #interface and adding NS_UNAVAILABLE
You don't need to do this, and the answer above does not, but if you need this assistance to your discipline you can add the declarations below - this list was produced by simply copying from NSString.h and a quick search & replace.
+ (instancetype) new NS_UNAVAILABLE;
+ (instancetype) alloc NS_UNAVAILABLE;
+ (instancetype) allocWithZone:(NSZone *)zone NS_UNAVAILABLE;
- (instancetype) init NS_UNAVAILABLE;
- (instancetype) copy NS_UNAVAILABLE;
- (instancetype) copyWithZone:(NSZone *)zone NS_UNAVAILABLE;
- (instancetype)initWithCharactersNoCopy:(unichar *)characters length:(NSUInteger)length freeWhenDone:(BOOL)freeBuffer NS_UNAVAILABLE;
- (instancetype)initWithCharacters:(const unichar *)characters length:(NSUInteger)length NS_UNAVAILABLE;
- (instancetype)initWithUTF8String:(const char *)nullTerminatedCString NS_UNAVAILABLE;
- (instancetype)initWithString:(NSString *)aString NS_UNAVAILABLE;
- (instancetype)initWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) NS_UNAVAILABLE;
- (instancetype)initWithFormat:(NSString *)format arguments:(va_list)argList NS_FORMAT_FUNCTION(1,0) NS_UNAVAILABLE;
- (instancetype)initWithFormat:(NSString *)format locale:(id)locale, ... NS_FORMAT_FUNCTION(1,3) NS_UNAVAILABLE;
- (instancetype)initWithFormat:(NSString *)format locale:(id)locale arguments:(va_list)argList NS_FORMAT_FUNCTION(1,0) NS_UNAVAILABLE;
- (instancetype)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding NS_UNAVAILABLE;
- (instancetype)initWithBytes:(const void *)bytes length:(NSUInteger)len encoding:(NSStringEncoding)encoding NS_UNAVAILABLE;
- (instancetype)initWithBytesNoCopy:(void *)bytes length:(NSUInteger)len encoding:(NSStringEncoding)encoding freeWhenDone:(BOOL)freeBuffer NS_UNAVAILABLE;
+ (instancetype)string NS_UNAVAILABLE;
+ (instancetype)stringWithString:(NSString *)string NS_UNAVAILABLE;
+ (instancetype)stringWithCharacters:(const unichar *)characters length:(NSUInteger)length NS_UNAVAILABLE;
+ (instancetype)stringWithUTF8String:(const char *)nullTerminatedCString NS_UNAVAILABLE;
+ (instancetype)stringWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) NS_UNAVAILABLE;
+ (instancetype)localizedStringWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) NS_UNAVAILABLE;
- (instancetype)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding NS_UNAVAILABLE;
+ (instancetype)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc NS_UNAVAILABLE;
- (instancetype)initWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error NS_UNAVAILABLE;
- (instancetype)initWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error NS_UNAVAILABLE;
+ (instancetype)stringWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error NS_UNAVAILABLE;
+ (instancetype)stringWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error NS_UNAVAILABLE;
- (instancetype)initWithContentsOfURL:(NSURL *)url usedEncoding:(NSStringEncoding *)enc error:(NSError **)error NS_UNAVAILABLE;
- (instancetype)initWithContentsOfFile:(NSString *)path usedEncoding:(NSStringEncoding *)enc error:(NSError **)error NS_UNAVAILABLE;
+ (instancetype)stringWithContentsOfURL:(NSURL *)url usedEncoding:(NSStringEncoding *)enc error:(NSError **)error NS_UNAVAILABLE;
+ (instancetype)stringWithContentsOfFile:(NSString *)path usedEncoding:(NSStringEncoding *)enc error:(NSError **)error NS_UNAVAILABLE;
Have you thought about the #define macro?
#define kTabChart #"Charts"
During the pre-processing step of compilation, the compiler will swap out all kTabChart w/ your desired constant.
If you want constants of your own custom class, then you will have to use const as user #JeremyP says in the linked answer
It's quite easy get the class/address of an object as a string, using:
NSString* objectInfoString = [object description];
The string returned is something like <ClassName: fk10009567>, with the letters and numbers representing it's unique address in memory, as I understand it.
Or, for just the address, simply using a formatted NSString with the %p place holder.
NSString* addressString = [NSString stringWithFormat:#"%p",myObject];
Is it then possible to create a pointer from this string information?
For Example:
NSObject* foo = [[NSObject alloc]init];
NSString* fooAddressString = [NSString stringWithFormat:#"%p",foo];
Then, I'd like to be able to do something like:
NSObject* newFoo = [NSObject objectForAddressString:fooAddressString];
such that newFoo = foo is true.
The foundation APIs provide a specific mechanism for doing this, without using 'magic strings', although you could do it using stringWithFormat, I guess. (It would be somewhat fragile, as noted).
To get a pointer reference to the object:
//Value now contains a pointer to the object, be careful it doesn't become dangling
NSValue* value = [NSValue valueWithPointer:(__bridge void*) myObject];
To get the object back from the pointer reference:
//If not using ARC you can skip the (__bridge id) here, and change the above cast to just (void*)
MyObjectType* myObject = (__bridge id) [value pointerValue];
Fragility?
It was noted that using '%p' to obtain a pointer value is fragile - while all Objective-C implementations currently return a hex value, the implementation of this could change. In any case, there's a specific API to do it.
Consider also that saving a reference to a pointer is fragile by nature in any case: Having obtained a pointer its necessary to ensure that it doesn't become 'dangling' - meaning the object being referenced goes away before the pointer does. The same strategies as using the __unsafe_unretained (aka assign) memory option should be applied. (No automatic weak references here!)
There are certainly valid applications of this kind of thing, however they are quite specialized and it would be unusual to find yourself doing this in everday apps programming. (I gathered you were asking the question simply to get a deeper understanding of Objective-C - kudos for that).
What is a valid use of this technique?
One valid application is to keep a reference to an Objective-C object in a C++ class. The Box2d physics engine (C++) allows this to provide an integration point with various Objective-C sprite engines.
This does not seem something sane or good thing to do. Relying on the - description of an object is very, very fragile. Why would you need to recover the object from its description? If you want to serialize and deserialize objects, you can do that by implementing the NSCoding protocol. If you want to associate objects with indices or keys, you can use NSArray or NSDictionary, etc...
That said, however, you can make a pointer out of a string:
NSString *addr = #"0xbadf00d";
uintptr_t ptr = strtoull(addr.UTF8String, NULL, 0);
id obj = (id)ptr;
In C there is a default implementation of equality operator. Go through all the member and verify that they satisfy the equality operator. The default is somewhat stupid because if an object contains pointer then the equality operator of the member would be performed on the pointer.
Still, it's good enough for my purpose.
So does it?
Or are we expected to implement isEqual and the corresponding hash for everytime we create a custom object that may we want to use isequal for.
It seems to me the "default" implementation is to simply compare the pointer of the object and not it's member. Am I correct here? It's even worse than C++ standard comparison. That's what I want to verify.
It seems to me if our class is the immediate children of NSObject then isEqual will simply call it's parent's isEqual and that simply compare pointers.
Am I correct here? I am just wanting to make sure of that.
I think that NSObject’s implementation does pointer comparison, and various other classes from the SDK do what’s most appropriate, ie. NSString does comparison on string contents, NSArray compares content equality, and so on. If you want to have “better” equality defined for your custom objects, you have to decide about the semantics and implement it yourself.
Its a little confusing because of the way Apple separates their docs between protocols and interfaces.
#protocol NSObject
- (BOOL)isEqual:(id)object;
This is a required method to be implemented so NSObject (the class) definitely implements this although you wouldnt know it from looking at the class definition on apples dev site. This is directly from the headers in xcode.
In general without implementing a custom isEqual you will expect to only get pointer identity and thats ok in many cases. Systems need to be designed around the way you identify unique instances regardless of the peculiarity of a particular feature such as hash and isEqual. If you need to test for object equality beyond the pointer then you just have to do that.
As NSObject provides isEqual:, and all your objects are descendants of NSObject, then the the simple answer is that a default implementation is provided.
Now you are concerned over the algorithm this default uses, and in a comment write "I wouldn't be sure simply by testing". Let's look at testing, just for fun ;-)
Now isEqual: is a rather fundamental method, if Apple decided to change its semantics the consequences could be significant and not good. So while Apple is free to change how it is implemented provided the semantics remain the same, which means the same objects compare equal after the change as before. Now you've mentioned three possible algorithms isEqual: could use:
Pointer comparison - is it the exact same object
Shallow comparison - do the fields of the object have the same value compared directly
Deep comparison - do the non-pointer-valued fields compared directly have the same value, and do the pointer-valued fields compare equal using isEqual:
These all have different semantics, whichever one Apple has chosen it can't change without breaking a lot of code. And different semantics means you can test...
Coding as I type, errors expected! Only important bits included:
#implementation A
- (BOOL) isEqual:(id)other
{
NSLog(#"A.isEqual called");
return self == other; // true iff same object
}
#end
#interface B
#property (readwrite) int anInteger;
#property (readwrite) A *anA;
#end
#implementation B
#synthesize anInteger, anA;
#end
// Let's test the algorithm
A *myA = [A new];
B *bOne = [B new];
B *bTwo = [B new];
bOne.anInteger = 42;
bOne.anA = myA;
bTwo.anInteger = 42;
bTwo.anA = myA;
// What output is produced (all of it!)
NSLog(#"[bOne isEqual:bTwo] -> %#", [bOne isEqual:bTwo] ? #"Yes" : #"No");
HTH a little.
I'm learning objective-c and keep bumping into the # symbol. It is used in different scenarios, for example at the start of a string or to synthesise accessor methods.
What's does the # symbol mean in objective-c?
The # character isn't used in C or C++ identifiers, so it's used to introduce Objective-C language keywords in a way that won't conflict with the other languages' keywords. This enables the "Objective" part of the language to freely intermix with the C or C++ part.
Thus with very few exceptions, any time you see # in some Objective-C code, you're looking at Objective-C constructs rather than C or C++ constructs.
The major exceptions are id, Class, nil, and Nil, which are generally treated as language keywords even though they may also have a typedef or #define behind them. For example, the compiler actually does treat id specially in terms of the pointer type conversion rules it applies to declarations, as well as to the decision of whether to generate GC write barriers.
Other exceptions are in, out, inout, oneway, byref, and bycopy; these are used as storage class annotations on method parameter and return types to make Distributed Objects more efficient. (They become part of the method signature available from the runtime, which DO can look at to determine how to best serialize a transaction.) There are also the attributes within #property declarations, copy, retain, assign, readonly, readwrite, nonatomic, getter, and setter; those are only valid within the attribute section of a #property declaration.
From Objective-C Tutorial: The # Symbol, the reason it is on the front of various keywords:
Using # should make it easier to bolt an Objective-C compiler on to an existing C compiler. Because the # isn't valid in any context in C except a string literal, the tokenizer (an early and simple step in the compiler) could be modified to simply look for the # character outside of a string constant (the tokenizer understands string literals, so it is in a position to distinguish this). When # is encountered the tokenizer would put the rest of the compiler in "Objective-C mode." (The Objective-C parser would be responsible for returning the compiler back to regular C mode when it detects the end of the Objective-C code).
Also when seen in front of a string literal, it makes an NSString rather than a 'char *' in C.
From Macrumors: Objective-C Tutorial, when in front of string literal:
There are also #"" NSString literals. It is essentially shorthand for NSString's +stringWithUTF8String method.
The # also adds unicode support to C strings.
From the manual:
Objective-C frameworks typically do not use C-style strings. Instead,
they pass strings around as NSString objects.
The NSString class provides an object wrapper for strings that has all
of the advantages you would expect, including built-in memory
management for storing arbitrary-length strings, support for Unicode,
printf-style formatting utilities, and more. Because such strings are
used commonly though, Objective-C provides a shorthand notation for
creating NSString objects from constant values. To use this shorthand,
all you have to do is precede a normal, double-quoted string with the
# symbol, as shown in the following examples:
NSString *myString = #"My String\n";
NSString *anotherString = [NSString stringWithFormat:#"%d %#", 1, #"String"];
As other answers have noted, the # symbol was convenient for adding Objective-C's superset of functionality to C because # is not used syntactically by C.
As to what it represents, that depends on the context in which it is used. The uses fall roughly into two categories (keywords and literals), and I've summarized the uses I could find below.
I wrote most of this before finding NSHipster's great summary. Here's another less thorough cheat sheet. (Both of those sources call things prefixed with # "compiler directives", but I thought compiler directives were things like #define, #ifdef, etc. If someone could weigh in on the correct terminology, I'd appreciate it.)
Objective-C Keywords
# prefixes many Objective-C keywords:
#interface: declares the methods and properties associated with a class
#implementation: implements a class's declarations from #interface
#protocol/#optional/#required: declares methods and properties that are independent of any specific class.
#class: forward declaration of a class
#property/#synthesize/#dynamic: declare properties in an #interface
#try/#throw/#catch/#finally: exception handling
#end: closes #interface, #implementation, and #protocol.
#encode: returns a C string that encodes the internal representation of a given type
#synchronized: ensures parallel execution exclusivity
#selector/#protocol: return SEL or protocol pointers with a specified name
#defs: I'm not really sure; it appears to import Objective-C class properties into a struct. NSHipster's page says it does not exist in modern Objective-C.
#public/#package/#protected/#private: access modifiers
#available: checks API availability.
#autoreleasepool: creates a new autorelease scope. Any objects that received an autorelease in the block will receive a release after exiting the block (and not before.)
Objective-C Literals
# creates Objective-C literals:
#...: NSNumber literal
NSNumber *fortyTwo = #42; // equivalent to [NSNumber numberWithInt:42]
NSNumber *yesNumber = #YES; // equivalent to [NSNumber numberWithBool:YES]
#(...): Boxed expressions
// numbers.
NSNumber *piOverTwo = #(M_PI / 2); // [NSNumber numberWithDouble:(M_PI / 2)]
// strings.
NSString *path = #(getenv("PATH")); // [NSString stringWithUTF8String:(getenv("PATH"))]
// structs.
NSValue *center = #(view.center); // Point p = view.center;
// [NSValue valueWithBytes:&p objCType:#encode(Point)];
#"...": Boxed C strings
#[]/#{}: Container literals
NSArray *array = #[ #"Hello", NSApp, [NSNumber numberWithInt:42] ];
NSDictionary *dictionary = #{
#"name" : NSUserName(),
#"date" : [NSDate date],
#"processInfo" : [NSProcessInfo processInfo]
};
I'm learning objective-c and keep bumping into the # symbol. It is used in different scenarios, for example at the start of a string or to synthesise accessor methods.
What's does the # symbol mean in objective-c?
The # character isn't used in C or C++ identifiers, so it's used to introduce Objective-C language keywords in a way that won't conflict with the other languages' keywords. This enables the "Objective" part of the language to freely intermix with the C or C++ part.
Thus with very few exceptions, any time you see # in some Objective-C code, you're looking at Objective-C constructs rather than C or C++ constructs.
The major exceptions are id, Class, nil, and Nil, which are generally treated as language keywords even though they may also have a typedef or #define behind them. For example, the compiler actually does treat id specially in terms of the pointer type conversion rules it applies to declarations, as well as to the decision of whether to generate GC write barriers.
Other exceptions are in, out, inout, oneway, byref, and bycopy; these are used as storage class annotations on method parameter and return types to make Distributed Objects more efficient. (They become part of the method signature available from the runtime, which DO can look at to determine how to best serialize a transaction.) There are also the attributes within #property declarations, copy, retain, assign, readonly, readwrite, nonatomic, getter, and setter; those are only valid within the attribute section of a #property declaration.
From Objective-C Tutorial: The # Symbol, the reason it is on the front of various keywords:
Using # should make it easier to bolt an Objective-C compiler on to an existing C compiler. Because the # isn't valid in any context in C except a string literal, the tokenizer (an early and simple step in the compiler) could be modified to simply look for the # character outside of a string constant (the tokenizer understands string literals, so it is in a position to distinguish this). When # is encountered the tokenizer would put the rest of the compiler in "Objective-C mode." (The Objective-C parser would be responsible for returning the compiler back to regular C mode when it detects the end of the Objective-C code).
Also when seen in front of a string literal, it makes an NSString rather than a 'char *' in C.
From Macrumors: Objective-C Tutorial, when in front of string literal:
There are also #"" NSString literals. It is essentially shorthand for NSString's +stringWithUTF8String method.
The # also adds unicode support to C strings.
From the manual:
Objective-C frameworks typically do not use C-style strings. Instead,
they pass strings around as NSString objects.
The NSString class provides an object wrapper for strings that has all
of the advantages you would expect, including built-in memory
management for storing arbitrary-length strings, support for Unicode,
printf-style formatting utilities, and more. Because such strings are
used commonly though, Objective-C provides a shorthand notation for
creating NSString objects from constant values. To use this shorthand,
all you have to do is precede a normal, double-quoted string with the
# symbol, as shown in the following examples:
NSString *myString = #"My String\n";
NSString *anotherString = [NSString stringWithFormat:#"%d %#", 1, #"String"];
As other answers have noted, the # symbol was convenient for adding Objective-C's superset of functionality to C because # is not used syntactically by C.
As to what it represents, that depends on the context in which it is used. The uses fall roughly into two categories (keywords and literals), and I've summarized the uses I could find below.
I wrote most of this before finding NSHipster's great summary. Here's another less thorough cheat sheet. (Both of those sources call things prefixed with # "compiler directives", but I thought compiler directives were things like #define, #ifdef, etc. If someone could weigh in on the correct terminology, I'd appreciate it.)
Objective-C Keywords
# prefixes many Objective-C keywords:
#interface: declares the methods and properties associated with a class
#implementation: implements a class's declarations from #interface
#protocol/#optional/#required: declares methods and properties that are independent of any specific class.
#class: forward declaration of a class
#property/#synthesize/#dynamic: declare properties in an #interface
#try/#throw/#catch/#finally: exception handling
#end: closes #interface, #implementation, and #protocol.
#encode: returns a C string that encodes the internal representation of a given type
#synchronized: ensures parallel execution exclusivity
#selector/#protocol: return SEL or protocol pointers with a specified name
#defs: I'm not really sure; it appears to import Objective-C class properties into a struct. NSHipster's page says it does not exist in modern Objective-C.
#public/#package/#protected/#private: access modifiers
#available: checks API availability.
#autoreleasepool: creates a new autorelease scope. Any objects that received an autorelease in the block will receive a release after exiting the block (and not before.)
Objective-C Literals
# creates Objective-C literals:
#...: NSNumber literal
NSNumber *fortyTwo = #42; // equivalent to [NSNumber numberWithInt:42]
NSNumber *yesNumber = #YES; // equivalent to [NSNumber numberWithBool:YES]
#(...): Boxed expressions
// numbers.
NSNumber *piOverTwo = #(M_PI / 2); // [NSNumber numberWithDouble:(M_PI / 2)]
// strings.
NSString *path = #(getenv("PATH")); // [NSString stringWithUTF8String:(getenv("PATH"))]
// structs.
NSValue *center = #(view.center); // Point p = view.center;
// [NSValue valueWithBytes:&p objCType:#encode(Point)];
#"...": Boxed C strings
#[]/#{}: Container literals
NSArray *array = #[ #"Hello", NSApp, [NSNumber numberWithInt:42] ];
NSDictionary *dictionary = #{
#"name" : NSUserName(),
#"date" : [NSDate date],
#"processInfo" : [NSProcessInfo processInfo]
};