Comparing Objects Directly to nil - objective-c

I have seen many posts here on Stack Overflow warning Objective-C users not to compare objects with the == operator. For example, the following is always recommended against.
if (string1 == string2) {} // string1 and string2 are both of type NSString *
I understand this warning as the == operator in this case checks for pointer equality, not the actual values of string1 and string2. If this is the case, why do I so often see people comparing their objects to nil with the == operator. For example, I have seen the following several times.
if (obj == nil) {} // obj is of type id, or any other object
If comparing pointers with the == operator is bad practice on things like NSStrings (or NSNumbers or NSArrays etc), then why is it so commonplace with nil.
Is this the standard because there is only one type of nil i.e.: nil always equals nil? Why are direct comaprisons using the == operator frowned upon between objects, but let slip when comparing to nil?
Thank your for your time.

Using == tests for pointer equality, which seems to be what you want to test for in this particular case. You are checking whether some pointer is a nil pointer. Specifically, a pointer that equals zero. Comparing objects is more complicated as you've pointed out. Equality between objects often relies on some internal part of the two objects being "the same".
In the case of strings, "equality" can mean "has the same characters" but it could also mean "has the same characters (ignoring capitalization)". There are also cases where you might want a nil string to equal an empty string or even a string with just whitespace. The point is that you must understand the different methods of determining equality in order to implement your own definition of equality for your objects.
Note that checking for pointer equality is almost never what you want to use when comparing things like strings or arrays. There are some interesting optimizations that can throw you off. For example, all empty NSArray's point to the same singleton object.

nil is like NULL from C or std::nullptr in C++. Basically points to nothing.
When a object in Objective-C is unallocated (haven't been alloc), the pointer will be nil.
So if (obj == nil) will check if obj is allocated (or initialized as they often happen together)
This technique is often used when writing a custom initializer or checking if some object exists or not.

Related

Do Apple templates contain a bug since they cast to BOOL?

According to Mike Ash's blog post casting to BOOL can fail 6% of the time since a pointer is larger than a BOOL. Because of this he recommends that if you are checking if an object exists you should check against nil
if (self != nil) {
instead of what Apple templates do which is
if (self) {
Do Apple's templates contain a bug or is there some other syntactical sugar I don't know about?
since they cast to BOOL
No, they don't. There is no cast performed at all. There is, however, evaluation of an expression as a logic value. In the case of pointers (which nil and self are), a NULL pointer evaluates to false, anything else to true. This is not a bug, just a shorthand way and it's perfectly valid C.
Concerning why one might want to perform an explicit comparison against NULL or nil: in some cases, it may be more readable, especially if it's not obvious at first glance of what type and range the expression is. However, in Objective-C and Cocoa, it's such a common idiom in a constructor to do this, that any experienced programmer will grasp it without problem.
Objective-C is based on C, and in C the if statement does, maybe surprisingly, not operate on boolean values.
C has a hierarchy of types:
The char, integer, and enumeration (enum) types are the integer types
The float, double and long double are the real floating types
There are three complex number types which together with the real floating types are termed simply the floating point types
The integer types and floating point types combined form the arithmetic types
The arithmetic types along with the pointer types form the scalar types
Phew!
Now to the if statement, it is of one of the forms:
if ( expression ) statement
if ( expression ) statement else statement
Where expression must be of any scalar type. The first (or only) statement is executed if the expression compares unequal to 0, the second (if present) statement is executed if the expression compares equal to 0.
So:
if (self) ...
and
if (self != nil) ...
are identical in result.
The first expression self is some pointer type, which is a scalar type, and is compared for being unequal to the zero of the pointer type (represented in code by nil). The second expression self != nil is an equality-expression and yields either 0 or 1 of type int, which is also a scalar type...
So technically the second form involves the intermediate production of an int value, but no compiler will actually produce one (unless you assign the result of the expression to a variable of course).
Notes:
Somewhat bizarrely if ( sin( angle ) ) ... is valid...
The switch statement operates on integer types and not scalar types
HTH
No, this can't fail if the pointer isn't nil, it's safe and the only difference is the syntax, and I wouldn't recommend one or another way, since they're the same.
You aren't casting self to a BOOL, you' re just checking if self is different from zero.
Edited
As per Martin's comment I was logging wrong debug messages.
It's the same
Here is a simple test
NSString *str = nil;
// suppose our string points to a string object whose starting address is 0x4500
//I'm assigning it manually so that I can test
str = 0x4500;
NSLog(#"%d",str);
if (str) {
NSLog(#"It's non-nil");
}
else {
NSLog(#"It's nil");
}
if (str == nil) {
NSLog(#"It's nil");
}
else {
NSLog(#"It's non-nil");
}
Output is :
It's non-nil
It's non-nil

please demystify this null

I am calling a web service in my project, for handling web service result there is a method, which tells what is returned by service. Other methods use this value for further process.
network problem, webserivce problem or any xyz reason, webserivce handling method return (null) value.
Now I have to perform nul checks, two approaches worked for me
if([val isEqualToString:#"(null)"]) ...
if(!val) ...
there are many questions regarding checking null, but not clearing my concepts.
Some says check length if I check the length like val.length it will be 6, because handler method return the "(null)". And !val I am not clear how this works. Some also says check isKindOfClass [NSNull null] ...
Please can any one demystify this null.
Please don't give comparison of nil vs Nil vs Null ...
if(!val) will test if val is null. That should be what you want to use, plain and simple. if(val == nil) is equivalent.
[val isEqualToString:#"null"] will, as the name suggests, test if val is equal to the string "null" which would most certainly make it not null.
[val isKindOfClass:[NSNull class]] has no relevance to you right now, so don't worry about it.
Edit since you asked for an explanation of NSNull:
Sometimes, you need to be able to store the concept of nil rather than nil itself.
Suppose you wanted an array with nil inside it. You want your array to look like [obj1, obj2, nil, obj3].
You can't declare an array like [NSArray arrayWithObjects:obj1, obj2, nil, obj3, nil] because as it goes through the arguments, when it sees nil it'll stop. This will result in the array [obj1, obj2], which is not what you wanted.
So what do you do in a situation like this? You make your array [NSArray arrayWithObjects:obj1, obj2, [NSNull null], obj3]. Now you have an object in your array, but this particular object is one that everyone in the system has agreed to call "null." It's not actually null.
What's really going on here is [NSNull null] is a singleton. When you call [NSNull null], it returns a static instance of NSNull. If you call [NSNull null] again, it'll return that same object, regardless of where you call the method. Because there is exactly one NSNull instance in the whole entire world of your app, it's equivalent to null because there will never be an object at that same address that doesn't have a null meaning.
So, as I said above, it's not relevant to you at all. You only need NSNull if you need a legitimate Objective-C object but you want it to be "null." It's usually safer to use NSNull than simply a string #"(null)" or something like that because it could be possible to overwrite the value of that string, mess up the string comparison, sometime down the line you might need to store the string #"(null)" in the same data structure as you're storing the null object, etc.

What does 'Nil' represent in Obj-C?

So there 's NULL, which is used for pointers in general, and nil, which is used for object pointers.
Now I see there's also Nil, which is used by lower-level Obj-C runtime functions like class_getProperty.
Is this somehow different from nil philosophically? (yes, I know they're all actually 0)
Why was it even introduced? Or, if Nil was first (which is likely), why was nil introduced?
Googling "Nil vs nil" found this post http://numbergrinder.com/node/49, which states:
All three of these values represent
null, or zero pointer, values. The
difference is that while NULL
represents zero for any pointer, nil
is specific to objects (e.g., id) and
Nil is specific to class pointers. It
should be considered a best practice
of sorts to use the right null object
in the right circumstance for
documentation purposes, even though
there is nothing stopping someone from
mixing and matching as they go along.

What describes nil best? What's that really?

Currently I understand it as a kind of "empty object". But what's it really?
Objective-C objects
First of all, when you call this:
id someObject = [NSArray array];
someObject isn't the array object directly but only a pointer to it. That means, if someObject is equal to 0x1234 there's an object at that address in the memory.
That's the reason why
id someOtherObject = someObject;
doesn't copy the object. Both pointers point now to the same object.
Pointer to 0x0
So, how is nil defined? Let's take a look at the source code:
objc.h
#define nil __DARWIN_NULL /* id of Nil instance */
_types.h
#ifdef __cplusplus
…
#else /* ! __cplusplus */
#define __DARWIN_NULL ((void *)0)
#endif /* __cplusplus */
Looks like nil is a pointer to the address 0x0.
So what?
Let's see what the Objective-C Programming Reference has to say:
Sending Messages to nil
In Objective-C, it is valid to send a
message to nil—it simply has no effect
at runtime. There are several patterns
in Cocoa that take advantage of this
fact. The value returned from a
message to nil may also be valid: …
The returned values are either nil, 0 or a struct with all variables initialized to 0. Which one it is depends on the expected return type. There is an explicit check in the objective-c runtime for messages to nil, that means it's really fast.
Nil, nil, NULL
Those are the 3 types. Here are all the definitions:
#define Nil __DARWIN_NULL /* id of Nil class */
#define nil __DARWIN_NULL /* id of Nil instance */
#define NULL __DARWIN_NULL
#define __DARWIN_NULL ((void *)0)
As can be seen, they are all exactly the same. Nil and nil are defined by Objective-C, NULL comes from C.
What's the difference then? It's only about style. It makes the code more readable.
Nil is used as a non-existent class: Class someClass = Nil.
nil is used as a non-existent instance: id someInstance = nil.
NULL is a pointer to a non-existent memory part: char *theString = NULL.
Short
nil isn't an empty object but a non-existent one. A method -getSomeObject doesn't return an empty object if it doesn't exist but returns nil which tells the user that there is no object.
Maybe this makes sense: (Both would compile and run.)
if (anObject == nil) { // One cannot compare nothing to nothing,
// that wouldn't make sense.
if (anObject) { // Correct, one checks for the existence of anObject
It's not an empty object, it's the lack of any object at all. The rest of the answers cover the other semantics, so I'll leave it at that :)
nil should only be used with pointers, and nil represents a pointer which points to nothing (it's value is zero)
NSString *myString = nil; // myString points to nothing
int x = nil; // invalid, "x" is not a pointer, but it will compile
It's "nothing". But a "nothing" you can send messages to without getting killed as you would if you were trying to call a method on NULL.
You can look at this question to have more info on NULL vs. nil
It's a null pointer - a pointer to "nothing".
Formally defined, it is as Joshual defined - a pointer to nothing or a pointer to no object at all.
From a practical, implementation perspective, particularly when dealing with data structures and algorithms, a nill often will represent a sentinel in a data structure or an object that represents "nothing" for example, in a red-black tree, technically, all of the leaf nodes are "nill", but they still have the same or similar properties & operations of a leaf node (color, pointer to a parent, etc.) - in those cases, it is really a "nothing object" ... if that makes any sense.
So, formally, it is a pointer to nothing, in practice, it is often treated as a representation of nothing, but it is never ... null.
One useful way of thinking about nil is imagining that it's the empty object that "does nothing".
By "does nothing" I mean, any message you send it won't have side effects.
It's "empty" in the sense that when you ask it for the value of any property, it always returns nil. So it's not holding any values --> it's empty.
(Actually, it's a little more complicated than that, when you ask for the value of a property that returns a type that's NOT an obj-c object. You will get back a pointer-sized 0. So for any scalar values that are no larger than sizeof(void*) you get 0. But if you ask for a struct or a double on a 32 bit system, you get an undefined result. I've written about this here.)
Maybe I'm just missing the obvious but this seems like a semantic question. As in, you can use lots of different words to describe it, but your description works well enough already.
http://en.wikipedia.org/wiki/Null_(computer_programming)
Just to clarify, in Objective-C nil and null are not the same thing. Neither do they represent the same thing in Objective-C as they do in mathematics or other programming languages.
Nil is actually a special memory address of 0x0 (at least the compiler treats it as an address.) Nil is used as the address of an object that is named but not allocated. This allows for test for the existence/allocation of named objects as well as providing a safe way to send messages to objects that might not exist. While in math and some languages you can compare scalar variables to nil, in Objective-c, you should not. You should only compare the address of objects.
NULL by contrast can mean either the standard C defined as an integer value ofNULL==0 or it can represents an actual allocated object of the class NSNull with a specific address in memory. NSNull is however, a singleton object i.e. only one exist for every application. It is used as placeholder for other objects usually in collections. You cannot use it in comparisons with any other object. You can only check if a particular pointer points to the singleton NSNull object. Note however that as an allocated object[NSNull null]!=NULL,
The confusion between nil and NULL arises because assigning an address of NULL assigns it to the nil address of 0x0. Such code works but can cause subtle problem at times. It's best to get in the habit of not confusing the two.
So, in Objective-C, nil, NUll and NSNull are three different but overlapping concepts that are easy to confuse. Nil should be used for addresses, NULL should be used for scalar values and NSNull should be used as a placeholder for allocated objects.

Sending a message to nil in Objective-C

As a Java developer who is reading Apple's Objective-C 2.0 documentation: I wonder what "sending a message to nil" means - let alone how it is actually useful. Taking an excerpt from the documentation:
There are several patterns in Cocoa
that take advantage of this fact. The
value returned from a message to nil
may also be valid:
If the method returns an object, any pointer type, any integer scalar
of size less than or equal to
sizeof(void*), a float, a double, a
long double, or a long long, then a
message sent to nil returns 0.
If the method returns a struct, as defined by the Mac OS X ABI Function
Call Guide to be returned in
registers, then a message sent to nil
returns 0.0 for every field in the
data structure. Other struct data
types will not be filled with zeros.
If the method returns anything other than the aforementioned value
types the return value of a message
sent to nil is undefined.
Has Java rendered my brain incapable of grokking the explanation above? Or is there something that I am missing that would make this as clear as glass?
I do get the idea of messages/receivers in Objective-C, I am simply confused about a receiver that happens to be nil.
Well, I think it can be described using a very contrived example. Let's say you have a method in Java which prints out all of the elements in an ArrayList:
void foo(ArrayList list)
{
for(int i = 0; i < list.size(); ++i){
System.out.println(list.get(i).toString());
}
}
Now, if you call that method like so: someObject.foo(NULL); you're going to probably get a NullPointerException when it tries to access list, in this case in the call to list.size(); Now, you'd probably never call someObject.foo(NULL) with the NULL value like that. However, you may have gotten your ArrayList from a method which returns NULL if it runs into some error generating the ArrayList like someObject.foo(otherObject.getArrayList());
Of course, you'll also have problems if you do something like this:
ArrayList list = NULL;
list.size();
Now, in Objective-C, we have the equivalent method:
- (void)foo:(NSArray*)anArray
{
int i;
for(i = 0; i < [anArray count]; ++i){
NSLog(#"%#", [[anArray objectAtIndex:i] stringValue];
}
}
Now, if we have the following code:
[someObject foo:nil];
we have the same situation in which Java will produce a NullPointerException. The nil object will be accessed first at [anArray count] However, instead of throwing a NullPointerException, Objective-C will simply return 0 in accordance with the rules above, so the loop will not run. However, if we set the loop to run a set number of times, then we're first sending a message to anArray at [anArray objectAtIndex:i]; This will also return 0, but since objectAtIndex: returns a pointer, and a pointer to 0 is nil/NULL, NSLog will be passed nil each time through the loop. (Although NSLog is a function and not a method, it prints out (null) if passed a nil NSString.
In some cases it's nicer to have a NullPointerException, since you can tell right away that something is wrong with the program, but unless you catch the exception, the program will crash. (In C, trying to dereference NULL in this way causes the program to crash.) In Objective-C, it instead just causes possibly incorrect run-time behavior. However, if you have a method that doesn't break if it returns 0/nil/NULL/a zeroed struct, then this saves you from having to check to make sure the object or parameters are nil.
A message to nil does nothing and returns nil, Nil, NULL, 0, or 0.0.
All of the other posts are correct, but maybe it's the concept that's the thing important here.
In Objective-C method calls, any object reference that can accept a selector is a valid target for that selector.
This saves a LOT of "is the target object of type X?" code - as long as the receiving object implements the selector, it makes absolutely no difference what class it is! nil is an NSObject that accepts any selector - it just doesn't do anything. This eliminates a lot of "check for nil, don't send the message if true" code as well. (The "if it accepts it, it implements it" concept is also what allows you to create protocols, which are sorta kinda like Java interfaces: a declaration that if a class implements the stated methods, then it conforms to the protocol.)
The reason for this is to eliminate monkey code that doesn't do anything except keep the compiler happy. Yes, you get the overhead of one more method call, but you save programmer time, which is a far more expensive resource than CPU time. In addition, you're eliminating more code and more conditional complexity from your application.
Clarifying for downvoters: you may think this is not a good way to go, but it's how the language is implemented, and it's the recommended programming idiom in Objective-C (see the Stanford iPhone programming lectures).
What it means is that the runtime doesn't produce an error when objc_msgSend is called on the nil pointer; instead it returns some (often useful) value. Messages that might have a side effect do nothing.
It's useful because most of the default values are more appropriate than an error. For example:
[someNullNSArrayReference count] => 0
I.e., nil appears to be the empty array. Hiding a nil NSView reference does nothing. Handy, eh?
In the quotation from the documentation, there are two separate concepts -- perhaps it might be better if the documentation made that more clear:
There are several patterns in Cocoa that take advantage of this fact.
The value returned from a message to nil may also be valid:
The former is probably more relevant here: typically being able to send messages to nil makes code more straightforward -- you don't have to check for null values everywhere. The canonical example is probably the accessor method:
- (void)setValue:(MyClass *)newValue {
if (value != newValue) {
[value release];
value = [newValue retain];
}
}
If sending messages to nil were not valid, this method would be more complex -- you'd have to have two additional checks to ensure value and newValue are not nil before sending them messages.
The latter point (that values returned from a message to nil are also typically valid), though, adds a multiplier effect to the former. For example:
if ([myArray count] > 0) {
// do something...
}
This code again doesn't require a check for nil values, and flows naturally...
All this said, the additional flexibility that being able to send messages to nil does come at some cost. There is the possibility that you will at some stage write code that fails in a peculiar way because you didn't take into account the possibility that a value might be nil.
From Greg Parker's site:
If running LLVM Compiler 3.0 (Xcode 4.2) or later
Messages to nil with return type | return
Integers up to 64 bits | 0
Floating-point up to long double | 0.0
Pointers | nil
Structs | {0}
Any _Complex type | {0, 0}
It means often not having to check for nil objects everywhere for safety - particularly:
[someVariable release];
or, as noted, various count and length methods all return 0 when you've got a nil value, so you do not have to add extra checks for nil all over:
if ( [myString length] > 0 )
or this:
return [myArray count]; // say for number of rows in a table
Don't think about "the receiver being nil"; I agree, that is pretty weird. If you're sending a message to nil, there is no receiver. You're just sending a message to nothing.
How to deal with that is a philosophical difference between Java and Objective-C: in Java, that's an error; in Objective-C, it is a no-op.
ObjC messages which are sent to nil and whose return values have size larger than sizeof(void*) produce undefined values on PowerPC processors. In addition to that, these messages cause undefined values to be returned in fields of structs whose size is larger than 8 bytes on Intel processors as well. Vincent Gable has described this nicely in his blog post
I don't think any of the other answers have mentioned this clearly: if you're used to Java, you should keep in mind that while Objective-C on Mac OS X has exception handling support, it's an optional language feature that can be turned on/off with a compiler flag. My guess is that this design of "sending messages to nil is safe" predates the inclusion of exception handling support in the language and was done with a similar goal in mind: methods can return nil to indicate errors, and since sending a message to nil usually returns nil in turn, this allows the error indication to propagate through your code so you don't have to check for it at every single message. You only have to check for it at points where it matters. I personally think exception propagation&handling is a better way to address this goal, but not everyone may agree with that. (On the other hand, I for example don't like Java's requirement on you having to declare what exceptions a method may throw, which often forces you to syntactically propagate exception declarations throughout your code; but that's another discussion.)
I've posted a similar, but longer, answer to the related question "Is asserting that every object creation succeeded necessary in Objective C?" if you want more details.
C represents nothing as 0 for primitive values, and NULL for pointers (which is equivalent to 0 in a pointer context).
Objective-C builds on C's representation of nothing by adding nil. nil is an object pointer to nothing. Although semantically distinct from NULL, they are technically equivalent to one another.
Newly-alloc'd NSObjects start life with their contents set to 0. This means that all pointers that object has to other objects begin as nil, so it's unnecessary to, for instance, set self.(association) = nil in init methods.
The most notable behavior of nil, though, is that it can have messages sent to it.
In other languages, like C++ (or Java), this would crash your program, but in Objective-C, invoking a method on nil returns a zero value. This greatly simplifies expressions, as it obviates the need to check for nil before doing anything:
// For example, this expression...
if (name != nil && [name isEqualToString:#"Steve"]) { ... }
// ...can be simplified to:
if ([name isEqualToString:#"Steve"]) { ... }
Being aware of how nil works in Objective-C allows this convenience to be a feature, and not a lurking bug in your application. Make sure to guard against cases where nil values are unwanted, either by checking and returning early to fail silently, or adding a NSParameterAssert to throw an exception.
Source:
http://nshipster.com/nil/
https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocObjectsClasses.html (Sending Message to nil).