nil vs kNilOptions

2020-06-17 05:23发布

问题:

I find some time ago the enum kNilOptions which is equal to 0. I try to make my code the most readable but I wonder what is best to use when you have methods that take an option parameter, for example :

[NSData dataWithContentsOfFile:imageURL.path
                               options:kNilOptions
                               error:&error];

I usually see nil in a lot of code I read but I think kNilOptions would be more accurate. I don't see often (almost never) kNilOptions. Is there a reason for that?

Do you think it is ok to use it or is it better to stick to simply nil?

回答1:

I think 0 is more readable than kNilOptions and there is some evidence that kNilOptions is "old".

You should use nil to represent uninitialized Objective-C object references and NULL for uninitialized C pointers (void *, char *, etc).

Use 0 if the options doesn't provide a "none value", which is the case for options NSDataReadingOptions.



回答2:

kNilOptions is an old constant intended to document that the 0 is not just any magic zero, but stands for “no options”. In that sense its use is valid, although personally I consider it quite ugly in an Objective-C context (most of its use seems to be in C) with the k prefix and all. Searching developer.apple.com for options:kNilOptions vs options:0 also shows that options:0 is their preferred style.

As for nil, it is the Objective-C equivalent of a null pointer for objects, and should not be used to stand in for the number 0 (as would be the case here).

When the argument is an enum type that includes its own “no options” value, you should use that, but in case of NSData the argument is not an enum but a typedef'd NSUInteger, and it does not have its own “no options” value defined.



回答3:

Even if Apple uses it, AppCode will warn you if you simply use 0 for an NSEnum/NSOption value, as you are using an integer instead of an Enum value.

So you need to either explicitly cast 0 to the correct Enum type:

[NSData dataWithContentsOfFile:imageURL.path
                       options:(NSDataReadingOptions)0
                         error:&error];

Or use kNilOptions which is an anonymous Enum value:

[NSData dataWithContentsOfFile:imageURL.path
                       options:kNilOptions
                         error:&error];

I recommend the later solution, kNilOptions instead of (NSDataReadingOptions)0, to avoid manually written C-cast.


The same issue arises for object pointers.

You need to either explicitly cast 0 to a pointer:

[NSData dataWithContentsOfFile:imageURL.path
                       options:readOptionsMask
                         error:(void*)0];

Or use nil which is a cast to a pointer itself:

[NSData dataWithContentsOfFile:imageURL.path
                       options:readOptionsMask
                         error:nil];

Everybody would recommend the later solution, nil instead of (void*)0, to avoid manually written C-cast.



回答4:

Various things that can end up being a zero are used for different purposes. Not using the correct one may not affect the code, but anyone reading your code will be suspicious and will get stuck verifying that the code does make sense.

  • 0 = the integer zero.

  • 0.0 = the double precision floating point number zero.

  • '\0' = the nul char, which is used as the delimiter of a C string.

  • NULL = a C or C++ pointer that doesn't point to anything.

  • nil = an Objective-C object pointer that doesn't point to any object (As an implementation detail, nil == 0 just happens to evaluate to true, but don't use nil instead of 0/false).

  • Nil = an Objective-C class pointer that doesn't point to any class.

  • kNilOptions (in this case) = an enumeration constant describing that there are no options.