在编码方法或函数时,检查输入参数以响应任何可能的失败情况是一种很好的做法。
例如:
-(void)insertNameInDictionary:(NSString*)nameString
{
[myDictionary setObject:nameString forKey:@"Name"];
}
这看起来不错,但如果
nameString
是 nil
,应用程序将崩溃。所以,我们可以检查它是否是 nil
, 对?。我们还可以检查它是否是 NSString 而不是 NSNumber 或者它是否响应我们的方法需要调用的方法。所以我的问题是:检查这些论点的最完整和最优雅的方法是什么?
最佳答案
有多种方法可以实现这种保护:
NSParameterAssert
__attribute__((nonnull))
if
测试。 [编辑]
从最新的 Xcode 版本 (Xcode 6) 开始,Apple 添加了 nullability annotations这是表达参数是否可以是
nil
的另一种——也是更好的——方式/null
或不。您应该迁移到该符号而不是使用 __attribute__((nonnull))
使您的 API 更具可读性。详细说明:
NSParameterAssert
是 Apple 的专用宏,用于检查方法参数的条件并在失败时抛出专用异常。nil
作为参数是编程/概念错误 ,考虑到由于您的应用程序工作流程,它通常永远不会发生(例如,由于其他条件确保参数永远不会是 nil
),并且如果它不是真的出了问题。 @try/@catch
),但它的优点是抛出的异常更加明确(告诉参数预计不是 nil
而不是因丑陋而崩溃)难以理解的调用堆栈/消息)。 nil
调用您的方法但在这种情况下什么都不做,你可以简单地if (!param) return
在函数/方法的开头。nil
不是编程/概念错误,因此有时可能由于应用程序的工作流程而发生,因此这是可能发生的可接受的情况,但不应崩溃。 __attribute__((nonnull))
GCC/LLVM attribute即 专用于告诉编译器某个函数/方法的某些参数预计不为空 .这样,如果编译器可以在编译时检测到您尝试使用 nil
调用您的方法/函数/NULL
参数(比如直接调用 insertNameInDitionary:nil
而不是使用一个在编译时还不能确定值的变量),它会立即发出编译错误让你尽快修复它。 __attribute__((nonnull))
.请参阅 Apple 博客文章中的示例。 所以总结一下:
如果你想标记你的方法 EXPECT 你的参数是非
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
在那个特定的例子中,简单地删除了 Name
来自 myDictionary
,你可以简单地做一个简单的 if
测试并调用 removeObjectForKey:@"Name"
如果 nameString
是 nil
并调用 setObject:forKey:
如果不是……或者您可以使用 KVC 和通用 setValue:forKey:
(KVC 方法,根本不特定于 NSDictionary,所以不要与 setObject:forKey:
混淆)在 NSDictionary 的情况下完全具有相同的行为(如果我们通过 nil
作为 value 参数,则从字典中删除键) .
关于ios - 在 Objective-C 中检查方法参数的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21054024/