There are several ways to implement this protection:
NSParameterAssert__attribute__((nonnull))- and a simple
if test.
[EDIT] Starting with the latest versions of Xcode (Xcode 6), Apple has added zero visibility annotations , which is different - and the best way to express if a parameter can be nil / null or not. You should switch to this notation instead of using __attribute__((nonnull)) to make your APIs even more readable.
More details:
NSParameterAssert is an Apple-highlighted macro that checks the condition for a method parameter and throws a thrown exception if it does not work.
- This is Runtime only protection .
- This macro also considers that passing
nil as a parameter is a programming / concept error , given that because of your application workflow it usually does not happen (due to other conditions, for example, nil ), and if it isnβt something really went wrong. - It still excludes (if your calling code can
@try/@catch if necessary), but it has the advantage that the exception thrown is more explicit (indicating that the parameter should not be nil instead of crashing with an ugly and hard-to-understand callstack / message).
If you want to allow the code to call your method using nil , but in this case just do nothing, you can simply if (!param) return at the beginning of the function / method.
- This holds that
nil passing is NOT a programming / concept error and therefore can sometimes happen due to the workflow of your application, so there is an acceptable case that can happen and just should not crash.
Less well-known, there is the __attribute__((nonnull)) GCC / LLVM attribute , which is intended to tell the compiler that some parameters of the / function are expected to be non-null . Thus, if the compiler can detect at compile time that you are trying to call your method / function using the nil / null argument (for example, directly call insertNameInDitionary:nil instead of using a variable whose value cannot be determined at compile time), it will immediately issue compilation error so you can fix it as soon as possible.
[EDIT] Since the last Xcode 6, you can (and should) use zero visibility annotations instead of __attribute__((nonnull)) . See Apple Blog Examples.
So in short:
If you want to note that your EXPECT method for your parameter was not nil , which indicates that calling it with nil is a logical mistake, you should do the following:
- (void)insertNameInDictionary:(NSString*)nameString __attribute__((nonnull)) { // __attribute__((nonnull)) allows to check obvious cases (directly passing nil) at compile time NSParameterAssert(nameString); // NSParameterAssert allows to check other cases (passing a variable that may or may not be nil) at runtime [myDictionary setObject:nameString forKey:@"Name"]; }
If you think that calling your method using nil might happen and is acceptable , and you just want to avoid a crash in these cases, just follow these steps:
-(BOOL)insertNameInDictionary:(NSString*)nameString { if (nameString == nil) return NO; [myDictionary setObject:nameString forKey:@"Name"]; return YES; }
And if you think you can insert the nil object into a dictionary , you can convert the nil value to NSNull in this particular case, so that it inserts the NSNull singleton, which is intended for such use (I used a short form of the ternary operator ?: To make the code more compact):
-(void)insertNameInDictionary:(NSString*)nameString { [myDictionary setObject:nameString?:[NSNull null] forKey:@"Name"]; }
And in the latter case, if you want the nil transfer in this particular example to simply remove Name from myDictionary , you can simply run a simple if test and call removeObjectForKey:@"Name" if nameString is nil and calls setObject:forKey: if this is not so ... or you can use KVC and the common setValue:forKey: (the KVC method is not specific to NSDictionary, so you should not be confused with setObject:forKey: , which in the case of NSDictionary has exactly the same behavior (removing the key from dictionary, if we pass nil for the parameter value).