有多种方法可以实现此类保护:
NSParameterAssert
__attribute__((nonnull))
- 和一个简单的
if
test.
[EDIT]自最新的 Xcode 版本(Xcode 6)以来,Apple 添加了可空性注释 https://developer.apple.com/swift/blog/?id=25这是另一种更好的方式来表达参数是否可以nil
/ null
或不。您应该迁移到该表示法而不是使用__attribute__((nonnull))
使您的 API 更具可读性。
详细信息:
-
NSParameterAssert
是 Apple 的专用宏,用于检查方法参数的条件,并在失败时抛出专用异常。
- 这是一个仅在运行时保护
- 这个宏还是认为通过
nil
作为参数是编程/概念错误,考虑到由于您的应用程序工作流程,它通常不会发生(由于其他条件确保参数永远不会发生)nil
例如),如果不是真的出了问题。
- 它仍然会抛出异常(您的调用代码可能会
@try/@catch
如果需要的话),但它的优点是抛出的异常更加明确(告诉参数预计不会是nil
而不是因丑陋且难以理解的调用堆栈/消息而崩溃)。
-
如果你想允许您的代码调用您的方法nil
但在这种情况下什么都不做,你可以简单地if (!param) return
在函数/方法的开头。
- 这认为通过
nil
不是编程/概念错误,因此有时会由于应用程序的工作流程而发生,因此这是可能发生的可接受的情况,并且不应崩溃。
不太为人所知的是,有__attribute__((nonnull))GCC/LLVM 属性 http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html#index-g_t_0040code_007bnoinline_007d-function-attribute-1732那是专门告诉编译器函数/方法的某些参数不应为空。这样,如果编译器可以在编译时检测到您尝试使用nil
/NULL
参数(比如直接调用insertNameInDitionary:nil
而不是使用在编译时还无法确定值的变量),它会立即发出编译错误,让您尽快修复它。
[EDIT]从最新的 Xcode 6 开始,您可以(并且应该)使用可空性注释 https://developer.apple.com/swift/blog/?id=25代替__attribute__((nonnull))
。请参阅 Apple 博客文章中的示例。
总结来说:
如果你想标记你的方法期望你的参数是非nil
,从而表明用nil
是一个逻辑错误,你应该执行以下操作:
- (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"];
}
如果你这么认为调用你的方法nil
可能发生并且是可以接受的,而您只是想避免在这些情况下发生崩溃,只需执行以下操作:
-(BOOL)insertNameInDictionary:(NSString*)nameString
{
if (nameString == nil) return NO;
[myDictionary setObject:nameString forKey:@"Name"];
return YES;
}
如果你这么认为你应该能够插入一个nil
字典中的对象,您可以将nil
价值NSNull
在这种特定情况下,以便它插入NSNull
单例专用于这种用法(我使用了缩写形式?:
三元运算符使代码更紧凑):
-(void)insertNameInDictionary:(NSString*)nameString
{
[myDictionary setObject:nameString?:[NSNull null] forKey:@"Name"];
}
最后一种情况,如果你想要通过nil
在那个特定的例子中removes the Name
from myDictionary
,你可以简单地做一个简单的if
测试并调用removeObjectForKey:@"Name"
if nameString
is nil
并打电话setObject:forKey:
如果不是……或者你可以使用 KVC 和通用的setValue:forKey:
(KVC 方法,根本不特定于 NSDictionary,所以不要与setObject:forKey:
)在 NSDictionary 的情况下具有完全相同的行为(如果我们通过,则从字典中删除键nil
为值参数)。