6

I just started reading the Objective-C tutorials, and there is a section on "sending a message to nil":

There are several patterns in Cocoa that take advantage of this fact. The value returned from a message to nil may also be valid:

What does this mean? I can't seem to follow it.

jscs
  • 63,694
  • 13
  • 151
  • 195
Blankman
  • 259,732
  • 324
  • 769
  • 1,199

5 Answers5

11

The special treatment of nil means that you can do the following:

SomeClass * someObject;
someObject = nil;
[someObject doSomething];

And you can be assured that nothing will happen.

Now, why is this important?

In Objective-C, sending a message to an object means telling that object to do something, or asking that object for some information. Some examples:

[someObject updateRecords]; // 1
x = [someObject size];      // 2

Line 1 sends someObject a message called updateRecords, and line 2 sends the same object a message called size, which is expected to return a value. These messages boil down to method calls, and the actual code that ends up being run is determined by the Objective-C runtime system, since Objective-C is a dynamically-typed language.

To determine which method to invoke, the runtime system reads information from the address of the object in question (someObject, in the examples above) to work out what class it is an instance of. Using that information, it is able to look up the appropriate method to call, and when all that has been figured out, it executes the code in the method.

If the runtime system did not treat nil as a special case, it would probably crash if you tried to execute the code shown at the top. nil is defined to be zero, so the runtime would start reading information from an address stored at location zero in memory, which is almost gauranteed to be an access violation.

e.James
  • 116,942
  • 41
  • 177
  • 214
  • 1
    So why in http://www.raywenderlich.com/2696/how-to-debug-memory-leaks-with-xcode-and-instruments-tutorial, they say "sending a message to deallocated memory causes a crash" ? – onmyway133 Jul 28 '13 at 16:28
  • 3
    Sending a message to deallocated memory (also known as a zombie) can happen if you release an object but still retain a pointer to the old memory location. For example: `[someObject release]; [someObject someMethod];`. This is very different from `someObject = nil; [someObject someMethod];` Even though setting someObject to nil may release it in a GC environment, the act of setting it to nil will also prevent you from sending a message to the *deallocated* memory. – e.James Jul 29 '13 at 23:56
11
  • nil is basically a null pointer (i.e. it is the number zero stored in a pointer).
  • All messages to nil are legal (they won't cause a crash), but they don't do anything.
  • All messages to nil return nil, or 0, or 0.0, or NO, depending on the return type.
Tom Dalling
  • 23,305
  • 6
  • 62
  • 80
  • 1
    Point 3 depends on the runtime. In older runtimes the documentation said you couldn't rely on the return value of messaging nil if the method returned floats, doubles or greater-than-natural-word-sized variables. – dreamlax Jul 02 '09 at 23:04
5

You can send any message to nil. Nothing happens.

What exactly is it you don't understand in those docs?

rincewind
  • 2,502
  • 19
  • 26
  • 1
    what is nil? Are you seding the value null to a object's method? or sending the value null to a message? what messagE? – Blankman Jul 02 '09 at 13:41
  • "nil" is a null object. If you're familiar with Java, "sending a message to nil" is equivalent to "calling a method on null" in Java, except that in Java, you get a NullPointerException, whereas in Objective-C, nothing happens. So you can safely do something like "[nil doThis:withThis]" and the program won't crash (the method will just return nil). – mipadi Jul 02 '09 at 14:12
  • 1
    Not exactly. Nil is equal to 0, it's not an object. This is why you can do the same thing with methods that return an integer value. There is a special NSNull object that you can use in collections classes, but it is not equal to nil. – Marc Charbonneau Jul 02 '09 at 15:04
  • @Marc: All objects evaluate equal to some integer. You can send messages to nil (something that is true of every object and not true of nonobjects in Objective-C), so conceptually at least, nil can meaningfully be called an object. It is a special value, though. – Chuck Jul 02 '09 at 15:10
  • 1
    "nil" usually refers to a nil instance and "Nil" usually refers to nil class. I think in the GNU runtime they are actually explicitly cast (id)0 and (Class)0, but I currently only have access to the NS runtimes. Pre 10.5 runtimes defined nil and Nil to just 0, but 10.5 defines them to __DARWIN_NULL. – dreamlax Jul 02 '09 at 23:11
2

The great thing about nil messaging compared to other languages like C# is that you can write code that performs multiple method calls without having to test for nil at each step.

id obj1 = [SomeClass object];
id obj2 = [obj1 doSomething];
id obj3 = [obj2 anotherMethod];

id thingICareAbout = [obj3 doSomethingElse];

If you go through several steps to get to thingICareAbout, it saves a lot of unnecessary lines of code to not have to test if obj1, obj2 and so on are nil before using them. You can just check if thingICareAbout is nil once at the end if you need to. Sometimes you don't even have to do that, if your code still works when it's nil (or 0 for primitive values).

In C# you would have had to explicitly check if each object is nil, set up exception handling around that block of code, or just hope none of the intermediate objects are ever nil.

One other thing to keep in mind (that I just learned myself!) is that 10.5 changed this behavior-- it used to be that it was only safe for integers and pointers to objects, not structs or floating point values. You might see some additional error checking when you're looking at other code because of this.

Marc Charbonneau
  • 40,399
  • 3
  • 75
  • 82
1

It does what you would expect: nothing.

Burkhard
  • 14,596
  • 22
  • 87
  • 108
  • 4
    Very few people that are familiar with popular languages such as Java, C# or C++ would expect this to do nothing. They'd expect an exception or a crash. – bacar Jan 28 '12 at 14:12