When should I use nil and NULL in Objective-C? - objective-c

This is sample code:
NSDictionary *myDictionary = [NSDictionary dictionary];
NSNumber *myNumber = [myDictionary valueForKey: #"MyNumber"];
NSLog(#"myNumber = %#", myNumber); // output myNumber = (null)
if (myNumber == nil)
NSLog(#"test 1 myNumber == nil");
if (myNumber == NULL)
NSLog(#"test 2 myNumber == NULL");
if ([myNumber isEqual:[NSNull null]])
NSLog(#"test 3 myNumber == [NSNull null]");
When should I use nil, NULL and [NSNull null]?

They differ in their types. They're all zero, but NULL is a void *, nil is an id, and Nil is a Class pointer.

You can use nil about anywhere you can use null. The main difference is that you can send messages to nil, so you can use it in some places where null cant work.
In general, just use nil.

nil is an empty value bound/corresponding with an object (the id type in Objective-C). nil got no reference/address, just an empty value.
NSString *str = nil;
So nil should be used, if we are dealing with an object.
if(str==nil)
NSLog("str is empty");
Now NULL is used for non-object pointer (like a C pointer) in Objective-C. Like nil , NULL got no value nor address.
char *myChar = NULL;
struct MyStruct *dStruct = NULL;
So if there is a situation, when I need to check my struct (structure type variable) is empty or not then, I will use:
if (dStruct == NULL)
NSLog("The struct is empty");
Let’s have another example, the
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
Of key-value observing, the context should be a C pointer or an object reference. Here for the context we can not use nil; we have to use NULL.
Finally the NSNull class defines a singleton object used to represent null values in collection objects(NSArray, NSDictionary). The [NSNull null] will returns the singleton instance of NSNull. Basically [NSNull null] is a proper object.
There is no way to insert a nil object into a collection type object. Let's have an example:
NSMutableArray *check = [[NSMutableArray alloc] init];
[check addObject:[NSNull null]];
[check addObject:nil];
On the second line, we will not get any error, because it is perfectly fair to insert a NSNull object into a collection type object. On the third line, we will get "object cannot be nil" error. Because nil is not an object.

NULL and nil are equal to each other, but nil is an object value while NULL is a generic pointer value ((void*)0, to be specific). [NSNull null] is an object that's meant to stand in for nil in situations where nil isn't allowed. For example, you can't have a nil value in an NSArray. So if you need to represent a "nil", you can use [NSNull null].

I've found the following:
objc.h
#define Nil __DARWIN_NULL /* id of Nil class */
#define nil __DARWIN_NULL /* id of Nil instance */
_types.h
#define __DARWIN_NULL ((void *)0)
stddef.h
#undef NULL
#ifdef __cplusplus
#undef __null // VC++ hack.
#define NULL __null
#else
#define NULL ((void*)0)
#endif
MacTypes.h
#ifndef NULL
#define NULL __DARWIN_NULL
#endif /* ! NULL */
#ifndef nil
#define nil NULL
#endif /* ! nil */
The way it looks, there's no difference but a conceptual one.

Beware that if([NSNull null]) returns true.

They both are just typecast zero's. Functionally, there's no difference between them.
ie.,
#define NULL ((void*)0)
#define nil ((id)0)
There is a difference, but only to yourself and other humans that read the code, the compiler doesn't care.
One more thing nil is an object value while NULL is a generic pointer value.

In modern OS X and iOS SDKs:
nil and Nil and NULL are identical in Objective-C and in
Objective-C++ before C++11.
nil and Nil and std::nullptr are
identical in Objective-C++ with C++11.
Stylistically, many people prefer to use nil for Objective-C objects and NULL or nullptr for other pointer types. I myself now use nil everywhere.
[NSNull null] is a singleton object use to represent null values in situations where nil is prohibited as a value (typically in a collection object such as an NSArray or NSDictionary). Number and Value Programming Topics: Using NSNull

To expand on a comment from #cobbal:
MacTypes.h contains:
#ifndef nil
#define nil NULL
#endif

As already mentioned, they are the same, but I use either the one or the other depending on the language in which the corresponding framework was written.
For everything related to Objective-C, I use nil. For example:
- (BOOL)doSomethingWithObjectsInArray:(NSArray *)anArray {
if (anArray == nil) return NO;
// process elements
...
}
However, when checking validity of data models from a C-framework (like AddressBook framework and CoreFoundation), I use NULL. For example:
- (BOOL)showABUnknownPersonVCForABRecordRef:(ABRecordRef)aRecord {
if (aRecord == NULL) return NO;
// set-up the ABUnknownPersonViewController and display it on screen
..
}
This way, I have subtle clues in my code if I'm dealing with Obj-C or C based code.

nil is an object pointer to nothing.
Although semantically distinct from NULL, they are technically equivalent to one another.
On the framework level, Foundation defines NSNull, which defines a class method, +null, which returns the singleton NSNull object. NSNull is different from nil or NULL, in that it is an actual object, rather than a zero value.
Additionally, in Foundation/NSObjCRuntime.h, Nil is defined as a class pointer to nothing.
Refer this for further info - nil / Nil / NULL / NSNull

There is a difference in some contexts.
Literally, Null is a character: ASCII 0.
Nil is equivalent to blank, no value.
Depending on the programming context, this can be a big difference.

Use NULL for example when you invoke an Objective-C method with an output parameter of type (NSError **).
I see lots of example code on the web where people provide nil instead of NULL in this case. This is because it's a pointer to a pointer and thus not directly an Objective-C object type. As said above, nil should be used for Objective-C object types.

Basically:
nil: null pointer on an object and
null: is for other type pointer

nil means absence of value while NULL represent No Object,
NSArray *array = #[#"Hello World !", #101,[NSNULL null] ];
Here [NSNULL null] is an object which means no object, at the same time you cannot add nil to indicate absence of object.
you can use both nil and [NSNUll null] for checking too.

This will help you to understand the difference between nil, NIL and null.
The below link may help you in some way:
http://nshipster.com/nil/
nil -> literal null value for Objective-C objects.
Nil -> literal null value for Objective-C classes.
NULL -> literal null value for C pointers.
NSNULL -> singleton object used to represent null.

Related

Null or Nil to return from method?

I'm writing a method and I want to return an object or lack of object if the method cannot find what it needs to. What's the best practice to return a lack of object, should it be [NSNull null] or nil? or it doesn't make any difference?
The convention is to return nil for Objective-C pointers (e.g. where the type is id, NSSomething *, UISomething *, etc.), NULL for arbitrary C pointers (e.g. int*, struct MyStruct*, void (*)(int).
[NSNull null] is only useful when you want to put a null value into an NS collection like NSArray or NSDictionary. So, [NSNull null] is a singleton Objective-C object that represents the null value (or the absence of value) by convention, there's nothing special about it otherwise.

How do I know what a return value of zero means for NSDictionary's objectForKey method in Objective C?

The documentation for NSDictionary says that the method objectForKey returns nil if the NSDictionary does not contain your key; however, isn't nil the same as zero? If so, how do I know if the return value means that the dictionary contains the key mapped to zero or if that key is just non-existant?
NSDictionaries (and, indeed, all Cocoa collection objects) can only contain Objective-C objects, not C primitives like int. Therefore, were you to store 0 in a dictionary, you'd do it like this:
[myDictionary setObject:[NSNumber numberWithInt:0] forKey:#"myKey"];
and therefore, retrieving it would go like this:
NSNumber* resultObj = [myDictionary objectForKey:#"myKey"];
if (resultObj == nil)
{
//Key didn't exist
}
else
{
int result = [resultObj intValue];
//Now do your work.
}
This concept of 'wrapping' a C primitive in an object to store it in a collection, then 'unwrapping' it on the other end is very common in Cocoa. (You might also look into NSValue if you're trying to work with non-number values.)
Edited: Although the direction in memory NULL and nil point to happen to be 0x0 and it has always been and it may always be, you can't use that value for other purposes but to define an undefined address in memory. In the case of NULL it means an undefined pointer. nil means an undefined object pointer. The idea behind these #defines is that there's a rigid standard for programmers and programs to know and communicate undefined addresses in memory, and it could change to 0x42 in a new compiler or standard and NOTHING should happen. So, don't think nil or NULL as 0; yes they are, but that's a mere accident. It's not a feature.
nil is not the same as 0. nil is an object pointer, 0 is a numeric value

Difference between nil, NIL and, null in Objective-C

I want to know the difference between nil, NIL and null.
I've googled around and found this:
nil -> null pointer to Objective-C object
NIL -> null pointer to Objective-C class
null -> null pointer to primitive type or absence of data
But I'm not able to understand the terms "Objective-C object" and "class" clearly.
Please explain this to me. Also, is there any word like NSNull or NSNil in Objective-C? If so, then please explain for what it is for.
nil is the literal null value for Objective-C objects, corresponding to the abstract type id or any Objective-C type declared via #interface. For instance:
NSString *someString = nil;
NSURL *someURL = nil;
id someObject = nil;
if (anotherObject == nil) // do something
Nil is the literal null value for Objective-C classes, corresponding to the type Class. Since most code doesn’t need variables to reference classes, its use is not common. One example is:
Class someClass = Nil;
Class anotherClass = [NSString class];
NULL is the literal null value for arbitrary C pointers. For instance,
int *pointerToInt = NULL;
char *pointerToChar = NULL;
struct TreeNode *rootNode = NULL;
NSNull is a class for objects that represent null. In fact, there’s only one object, namely the one returned by +[NSNull null]. It is different from nil because nil is a literal null value, i.e., it isn’t an object. The single instance of NSNull, on the other hand, is a proper object.
NSNull is often used in Foundation collections since they cannot store nil values. In the case of dictionaries, -objectForKey: returns nil to indicate that a given key has no corresponding object in the dictionary, i.e., the key hasn’t been added to the dictionary. If you want to make it explicit that you have a certain key but it doesn’t have a value yet, you can use [NSNull null].
For instance, the following throws an exception because dictionaries cannot store nil values:
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:nil forKey:#"someKey"];
On the other hand, the following code is valid since [NSNull null] is a non-nil object:
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[NSNull null] forKey:#"someKey"];
It’s worth mentioning that Foundation collections have initialisers that use nil as a marker for the end of a list of objects without having to specify the number of elements in the list. This can only happen because nil cannot be stored in a Foundation collection. For instance,
NSArray *array = [NSArray arrayWithObjects:#"one", #"two", nil];
As for NIL or NSNil, there are no such things in Objective-C or Apple Foundation.
I am not sure but i think nil should only be used in place of an id, what Java and C++ programmers would think of as a pointer to an object. Use NULL for non-object pointers.
nil is usually used for an Objective-C object type, while NULL is used for c-style pointers
Nil,Null and nil are used with below
1> Nil for Objective c Class
2> nil for Objective c object
3> Null for C pointer
Example:
1>Class A=Nil;
2>NSString strName=nil;
3>char *pointerChar = NULL;
Suppose you have a class MyClass
then by convention nil is used if you want to initialize its instance to null value (same as null in java)
i.e.
MyClass *obj = nil;
and if you want to initialize a primitive pointer to null value (same as in c) you use
int *ptr = NULL;
and if you want to initialize to Class reference to null value (same as null in java) then use
Class classRefOfMyClass = Nil;
It's just a convention otherwise Nil or nil have same meaning and perhaps NULL , nil or Nil all are same.
Here is the definition for these in objc.h file
#ifndef Nil
# if __has_feature(cxx_nullptr)
# define Nil nullptr
# else
# define Nil __DARWIN_NULL
# endif
#endif
#ifndef nil
# if __has_feature(cxx_nullptr)
# define nil nullptr
# else
# define nil __DARWIN_NULL
# endif
#endif
And in stddef.h
#define NULL ((void*)0)
And the definition of __DARWIN_NULL in _types.h
#define __DARWIN_NULL ((void *)0)
So there is no difference logically. The main idea here is to initialize a pointer whether C or Objective-C to 0. If you have knowledge of C then you can assign
int *ptr = 0;
without type casting 0 to a pointer. As you don't need to typecast 0 to assign it to a pointer.
In short they all are 0 and nothing else.
This will help you to understand the difference between nil,NIL and null.
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.
The below link may help you in some way:
http://nshipster.com/nil/
Here is some important part from the link:
nil, NIL and null. is depended on your requirement.
NSNull
collections like NSArray and NSDictionary not being able to contain nil values.
NSMutableDictionary *MymutableDictionary = [NSMutableDictionary dictionary];
MymutableDictionary[#"someKey"] = [NSNull null]; // Sets value of NSNull singleton for "someKey"
NSLog(#"Keys: %#", [mutableDictionary allKeys]);
nil
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.
In other languages, like C++, this would crash your program, but in Objective-C, invoking a method on nil returns a zero value.
if (name != nil)
{
........
}
Symbol Value Meaning
nil (id)0 literal null value for Objective-C objects
Nil (Class)0 literal null value for Objective-C classes

TouchJSON, dealing with NSNull

Hi
I am using TouchJSON to deserialize some JSON. I have been using it in the past and on those occasions I dealt with occurrences of NSNull manually. I would think the author had to deal with this as well, so me doing that again would just be overhead. I then found this in the documentation:
Avoiding NSNull values in output.
NSData *theJSONData = /* some JSON data */
CJSONDeserializer *theDeserializer = [CJSONDeserializer deserializer];
theDeserializer.nullObject = NULL;
NSError *theError = nil;
id theObject = [theDeserializer deserialize:theJSONData error:&theError];}
The way I understand it the user of the class can pass a C-style null pointer to the deserializer and when it encounters a NSNull it will insert the values (NULL) passed to it. So later on when I use the values I won't get NSNull, but NULL.
This seems strange, the return value is an NSDictionary which can only contain Objects, shouldn't the value default to 'nil' instead?
If it is NULL can I check the values like this?
if([jsonDataDict objectForKey:someKey] == NULL)
It would seem more logically to be able to do this:
if(![jsonDataDict objectForKey:someKey])
No to mention all the cases where passing nil is allowed but passing NULL causes a crash.
Or can I just pass 'nil' to the deserializer?
Much of this stems from me still struggling with nil, NULL, [NSNULL null], maybe I am failing to see the potential caveats in using nil.
For another JSON library, but with the same issues, I've created the following category on NSDictionary:
#implementation NSDictionary (Utility)
// in case of [NSNull null] values a nil is returned ...
- (id)objectForKeyNotNull:(id)key {
id object = [self objectForKey:key];
if (object == [NSNull null])
return nil;
return object;
}
#end
Whenever I deal with JSON data from said library, I retrieve values like this:
NSString *someString = [jsonDictionary objectForKeyNotNull:#"SomeString"];
This way the code in my projects become a lot cleaner and at the same time I don't have to think about dealing with [NSNull null] values and the like.
nil and NULL are actually both equal to zero, so they are, in practice, interchangeable. But you're right, for consistency, the documentation for TouchJSON should have used theDeserializer.nullObject = nil instead of NULL.
Now, when you do that, your second predicate actually works fine:
if (![jsonDataDict objectForKey:someKey])
because TouchJSON omits the key from the dictionary when you have nullObject set to nil (or NULL). When the key doesn't exist in the dictionary, NSDictionary returns nil, which is zero so your if condition works as you expect.
If you don't specify nullObject as nil, you can instead check for null like so:
if ([jsonDataDict objectForKey:someKey] == [NSNull null])
There are libraries which deal with it. One of them is SwiftyJSON in Swift, another one is NSTEasyJSON in Objective-C.
With this library (NSTEasyJSON) it will be easy to deal with such problems. In your case you can just check values you need:
NSTEasyJSON *JSON = [NSTEasyJSON withData:JSONData];
NSString *someValue = JSON[someKey].string;
This value will be NSString or nil and you should not check it for NSNull, NULL yourself.

Are NULL and nil equivalent?

Actually my question here is: are null and nil equivalent or not?
I have an example but I am confused when they are equal when they are not.
NSNull *nullValue = [NSNull null];
NSArray *arrayWithNull = [NSArray arrayWithObject:nullValue];
NSLog(#"arrayWithNull: %#", arrayWithNull);
id aValue = [arrayWithNull objectAtIndex:0];
if (aValue == nil) {
NSLog(#"equals nil");
} else if (aValue == [NSNull null]) {
NSLog(#"equals NSNull instance");
if ([aValue isEqual:nil]) {
NSLog(#"isEqual:nil");
}
}
Here in the above case it shows that both null and nil are not equal and it displays "equals NSNull instance"
NSString *str=NULL;
id str1=nil;
if(str1 == str)
{
printf("\n IS EQUAL........");
}
else
{
printf("\n NOT EQUAL........");
}
And in the second case it shows both are equal and it displays "IS EQUAL".
Anyone's help will be much appreciated.
Thank you,
Monish.
nil and NULL are essentially the same, nil is something like (NSObject *)0, while NULL is more like (void *)0. But both are pointers with an integer value of zero. You can send messages to nil without raising an error.
NSNull and NULL (or nil, of course) are different things, however. You just use NSNull as a helper to add an empty object to an NSArray or another container class, since you can't add nil to them. So instead, you use [NSNull null] as a replacement, and you have to check if an array element is NSNull, not if it's nil (it will never be equal to nil).
From http://www.iphonedevsdk.com/forum/iphone-sdk-development/34826-nil-vs-null.html
nil and NULL are 100% interchangeable.
From:
NULL is for C-style memory pointers.
nil is for Objective-C objects.
Nil is for Objective-C classes.
Whenever you're writing Objective-C code, use nil
Whenever you're writing C code, use NULL
But ultimately they're all defined as the same thing -- (void *)0, I think -- so in practice it doesn't really matter.
The concept is the same, with the difference that it's valid to send messages (call method) to nil.
NSNull is a real (singleton) class, that can be used for arrays or dictionnaries, who don't accept NULL or nil values.
Biggest difference between them: sending a message to an NSNULL object is probably going to cause a crash, whereas it's cool to send any message to nil. For example, if you use a key path to get an array, like so:
NSArray *departmentNames = [departments valueForKey:#"name"];
Then you will have an NSNULL object for any department whose name is nil. So, this is going to cause a crash:
for (NSString *name in departmentNames)
NSLog(#"%#", [name lowercaseString]);
whenever name is NSNull, because you just sent an unknown selector (lowercaseString) to an NSNull.
Lesson: check for the NSNull object in an array before sending any message to its elements.
for (NSString *name in departmentNames)
if (name != [NSNull null])
NSLog(#"%#", [name lowercaseString]);
No, NSNull and nil are not the same. They both represent a lack of value, and you might want to treat them the same, but they are still not equal.
The NSNull object instance represents a null value, for example when you read data from a database that has null values.
The nil value is a null pointer, i.e. it doesn't point to any object instance.
In your second code you don't have any NSNull instance. An NSString pointer that contains a null pointer is not an NSNull instance, it's still just a null pointer. You are comparing one null pointer to another, and they are of course equal.
Make sure you typecast [NSNull null] to object type that you are comparing
NSArray list;
if(list==(NSArray *)[NSNull null])
// do something
otherwise you will receive a warning message saying "Comparison of distinct pointer types('type *' and 'NSNull *')