How do I override the truth-value of my class instance, or its ! operator?
For example (simplified names/usage):
MyClass variable = [MyClass alloc] initWithValue: nil];
...
if (!variable) { NSLog(#"'Not variable value' works"); }
I've searched for two possible solutions but couldn't find anything useful. In some languages i would overload an isTrue, asBool, etc function; or override the unary ! operator FOR THAT CLASS (not the main NOT operator.
My initial reaction to this problem was: You don't need to in Objective-C, you're going at it wrong. While true, I have lost over hours debugging some code that had the above (!variable) instead of
if (!variable.value) { NSLog(#"'Not variable value' works"); }
MyClass has property value among many others, which you can set or not. It defines whether or not you do something so it is common to need if (!variable.value){ NSLog(#"Warning, value not set"); }
So I want to overload the ! or isTrue function to check whether or not variable.value is set instead of merely checking if variable is linked to an address. This would make my code more readable and make my class more useable.
To be clear, in this example, variable points to an alloc-init'ed object, where variable.value = nil for example.
For example this can be done in python by overloading __ nonzero __.
As a side question that would answer this question: How does the truth value of an object work in Objective-C?
You can't override these things in ObjC. ObjC behaves just like C in this regard-- object references are pointers, either valid or nil-- a nil value evaluates to NO in a boolean expression and any non-nil value will appear as YES.
The canonical check for "is this thing an invalid pointer" is if (!thing) { ... }.
If you are always doing this:
if (!variable.value) ...
then perhaps variable is of type NSNumber or some object container for a primitive? It's hard to tell without context what pattern you're using and whether there's a better idiom for this.
An object in Objective-C has the same meaning in a boolean expression as a pointer in C, because it is a C pointer. If the pointer is NULL -- or nil for an object -- then it's false; otherwise it's true.
You can't override operators in Objective-C.
This said, !variable.value does indeed test whether value is nil (assuming that value has an object type) -- the dot operator resolves to a message send [variable value] whose return value is then negated.
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.
How would I dealloc a boolean value?
Deallocing it this way below gives me a warning: Incompatible pointer to integer conversion assigning to 'BOOL' (aka 'signed char') from 'void *'
- (void)dealloc {
self.booleanVar = nil;
[super dealloc];
}
Perhaps I should clarify, this is from a simple class inherited from NSObject.
I'm using the self.var = nil pattern that you see in Cocoa Touch classes. Let's say if it was an NSString* instead should I use self.var = nil or [var release] in the deallocmethod? I'm a little confused here.
You don't need to do it. It is not an object. This also explains the warning, as you're trying to assign a nil pointer (that's a NULL for objects basically) to a non-object.
Regarding your second question, yes. You can think of primitive variables as being part of the object, so when it's deallocated the vars will not exist anymore.
But when you have a NSString * in an object, it's just a pointer to another object. If you dealloc the former, the pointer will be deleted, not the NSString. No one might point to it, it's kind of lost in the air, occupying memory. So, before deleting the pointer, if you won't need the object anymore, you send it a release message. That's done in the dealloc method, since it's called to "delete" and object and thus is a good place to delete also every other object that has no use anymore.
You dont need to dealloc a BOOL, since BOOLs are really just a byte, which is a primitive data type. You only need to dealloc objects which have been allocated to memory.
First of all, if booleanVar is just a plain BOOL value, as in it is declared like so:
BOOL booleanVar;
then you do not need to free up any memory associated with it, since that memory is allocated and freed when the class that holds it is allocated and deallocated. So no code for booleanVar in dealloc will be fine.
However, if you are talking about a pointer for a BOOL, defined like so:
BOOL *booleanVar;
and what you want is to set this variable to a non-value, you should set it equal to NULL instead of nil, since NULL is for value pointers and nil is for object pointers (see: NULL vs nil in Objective-C).
However, if what you want is to free up the memory that the BOOL pointer points to, allocated with malloc or realloc, etc, then try the free() C function (see: http://www.cplusplus.com/reference/clibrary/cstdlib/free/).
What would really clear all this up is if you showed us the property declaration for booleanVar in the class interface, which would tell us exactly what you want to do and you would get an answer with complete certitude.
This question already has answers here:
Sending a message to nil in Objective-C
(11 answers)
Closed 9 years ago.
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.
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.
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.
You can send any message to nil. Nothing happens.
What exactly is it you don't understand in those docs?
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.
It does what you would expect: nothing.
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).