Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending a message to nil in Objective-C

Tags:

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.

like image 982
Ryan Delucchi Avatar asked Oct 01 '08 06:10

Ryan Delucchi


People also ask

What is nil on message?

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.

What happens when you invoke a method on a nil pointer Objective-C?

You can validly send any message to a "nil" pointer in Objective-C. This is very different to languages like C++ where invoking a method on a "NULL" pointer will likely crash your program. Sending a message to "nil" will have only one effect: it will return a zero value. No other action will occur.

What happens when you invoke a method on a nil pointer Swift?

What happens when you invoke a method on a nil pointer? Nothing. This is important because, in Objective-C, sending a message to an object means telling that object to do something, or asking that object for some information. If the runtime system did not treat nil as a special case, it would probably crash.


1 Answers

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.

like image 150
Michael Buckley Avatar answered Sep 21 '22 08:09

Michael Buckley