在 Objective-C 中检查方法参数的最佳方法是什么?

2024-02-29

在对方法或函数进行编码时,最好检查输入参数以响应任何可能的失败情况。

例如:

-(void)insertNameInDictionary:(NSString*)nameString
{
    [myDictionary setObject:nameString forKey:@"Name"];
}

这看起来不错,但如果nameString is nil,应用程序将崩溃。所以,我们可以检查一下是否是nil, 正确的?。我们还可以检查它是否是 NSString 而不是 NSNumber,或者它是否响应我们的方法需要调用的方法。

所以我的问题是:检查这些论点的最完整和最优雅的方法是什么?


有多种方法可以实现此类保护:

  • NSParameterAssert
  • __attribute__((nonnull))
  • 和一个简单的if test.

[EDIT]自最新的 Xcode 版本(Xcode 6)以来,Apple 添加了可空性注释 https://developer.apple.com/swift/blog/?id=25这是另一种更好的方式来表达参数是否可以nil / null或不。您应该迁移到该表示法而不是使用__attribute__((nonnull))使您的 API 更具可读性。


详细信息:

  1. NSParameterAssert是 Apple 的专用宏,用于检查方法参数的条件,并在失败时抛出专用异常。

    • 这是一个仅在运行时保护
    • 这个宏还是认为通过nil作为参数是编程/概念错误,考虑到由于您的应用程序工作流程,它通常不会发生(由于其他条件确保参数永远不会发生)nil例如),如果不是真的出了问题。
    • 它仍然会抛出异常(您的调用代码可能会@try/@catch如果需要的话),但它的优点是抛出的异常更加明确(告诉参数预计不会是nil而不是因丑陋且难以理解的调用堆栈/消息而崩溃)。
  2. 如果你想允许您的代码调用您的方法nil但在这种情况下什么都不做,你可以简单地if (!param) return在函数/方法的开头。

    • 这认为通过nil不是编程/概念错误,因此有时会由于应用程序的工作流程而发生,因此这是可能发生的可接受的情况,并且不应崩溃。
  3. 不太为人所知的是,有__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而不是使用在编译时还无法确定值的变量),它会立即发出编译错误,让您尽快修复它。

  4. [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为值参数)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Objective-C 中检查方法参数的最佳方法是什么? 的相关文章

  • 适用于 IOS 和 Android 的支付网关 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在开发一个应用程序 用户必须在澳大利亚餐馆通过应用程序 android ios 付款 有两种付款方式 通过 PayPal 或 Visa
  • 从命令行调试 iOS 应用程序构建

    我正在通过命令行构建 iOS 应用程序 但在调试它时遇到问题 如果我使用 XCode 进行构建 它会让我在设备上 构建和调试 而不会出现任何问题 但现在 我不知道如何使用 gdb 在设备上启动它并逐步执行它 如果我尝试 添加自定义目标 可执
  • UIDocumentInteractionController 阻止“打开方式”表中的空投

    在我的应用程序中 我允许用户通过 Instagram 分享照片 这需要使用 UIDocumentInteractionController 如果手机支持 则会自动检测空投 如何将其从 打开方式 操作表中删除 即使我使用 UIActivity
  • 在带有 Storyboard 的 XCode 4 中以模态方式推送视图时,出现“对开始/结束外观转换的不平衡调用”警告

    在网上进行了一些研究但没有成功后 我来这里向您询问有关我的警告的问题 实际上 我有一个带有导航控制器的视图 V1 我想在 V1 完成加载时推送模态视图 V2 所以我用performSegueWithIdentifier方法 我正在使用故事板
  • 在 macOS 上为 MoviePy 安装 ffmpeg 失败并出现 SSL 错误

    我正在尝试编写一个 Python 程序 在 Mac OS 10 11 16 上使用 MoviePy 将 MP4 文件转换为 GIF 我用 import moviepy editor as mp 我收到一条错误消息 说我需要打电话imagei
  • VLCJ 无法在 Mac 上运行 - 插件 libvlccore.5.dylib

    我正在尝试让 VLCJ 在 Mac 和 PC 上运行 它在 Windows 7 64 位 下运行良好 但当我尝试在 Mac 上运行它时 它崩溃了 我指向 VLC dylib 文件的正确目录 但收到 使用 libvlccore 5 dylib
  • iOS 中的构建对象文件扩展名是什么?

    当我在项目中构建java对象类时 将创建带有 class扩展名的构建文件 并且人类不可读 快速构建文件怎么样 example car java gt build gt car class 构建后会是什么 car swift gt build
  • 如何恢复消耗品应用内购买?

    我正在开发一款 iOS 游戏 用户可以通过应用内消耗品购买一定数量的内部货币 比如 1000 金币 如果用户想将余额从一台设备转移到另一台设备 如何恢复消耗品购买 在苹果的文档中 它说我们必须使用我们自己的服务器 但是如何获取用户的Appl
  • 架构armv7的重复符号

    尝试在我现有的应用程序中使用 Layar SDK 时出现以下错误 我该如何解决这个问题 Ld Users pnawale Library Developer Xcode DerivedData hub afxxzaqisdfliwbzxbi
  • 频繁绘制 CGPath 时的性能

    我正在开发一个将数据可视化为折线图的 iOS 应用程序 该图被绘制为CGPath在全屏自定义中UIView最多包含 320 个数据点 数据经常更新 图表需要相应地重新绘制 刷新率为 10 秒就很好了 到目前为止很容易 然而 我的方法似乎需要
  • 来自 iPhone/iPad 的 json Web 服务

    有人可以帮助我解决如何从 iphone 或 ipad 使用 json Web 服务的问题吗 这里我的要求是使用 API 密钥实现 json webservice 如果可能的话发布一些教程或示例链接 谢谢 规范的 JSON 处理库是here
  • Google 地图 API -> OpenGLES 崩溃

    日志是从 Crashlytics 粘贴的 对于许多用户来说 崩溃经常发生 据我所知 它与设备 iOS 版本无关 我在我的代码中找不到任何错误 这似乎是纯粹的库问题 是 Google 地图 API 错误吗 我可以做些什么来修复它 或者我应该在
  • 指定访问组时出现 KeychainItemWrapper 错误

    相当长一段时间以来 我一直在使用 KeychainItemWrapper 的 ARC 版本成功读取和写入私有钥匙串项目 我现在正在努力将我的 iOS 应用程序转换为使用共享访问组 以便我的 2 个共享相同应用程序前缀的应用程序可以访问钥匙串
  • 为什么我的视图仍然以横向呈现?

    我的视图是由导航控制器控制的 因此我将导航控制器支持的方向设置为明确的纵向和纵向UpSideDown 这可以工作 但是如果调用视图时前一个视图处于横向状态 它将以横向方式呈现并保持横向状态 直到设备旋转 如何防止这种情况发生 这是我的代码
  • iPhone 和加密库

    我想我必须在我的 iPhone 应用程序中使用加密库 我想问你有关苹果公司实施的加密货币出口政策的影响 我需要做一些额外的事情吗 例如填写表格等 1 如果我使用 MD5 进行哈希处理 2 如果我使用对称加密 Thanks EDIT 2009
  • 苹果企业程序分发问题[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 这个问题涉及到Apple iOS 开发者企业计划 http developer apple com programs ios enterprise 我
  • OSX bash 最小化窗口

    在 Mac 中并使用 bash shell 我想执行一个包含单个命令 启动 Jupyter Lab 的文件并立即最小化终端窗口 有没有办法在不安装第三方软件的情况下做到这一点 是的 只需使用osascript https ss64 com
  • 避免 UIImage 的 imageNamed - 内存管理

    我正在经历这个链接 http akosma com 2009 01 28 10 iphone memory management tips 我遇到了一个点避免 UIImage 的 imageNamed 出于什么原因我们应该避免这种情况 它会
  • 使用基于约束的布局自动调整 NSTokenField 的大小

    有没有办法自动调整大小height使用约束的 NSTokenField 保持宽度恒定 sizeToFit应该有效 但事实并非如此 如果我设置一个约束来保持宽度不变并调用此方法 它将忽略约束并仅调整宽度大小 当我想要的是仅调整高度大小时 基于
  • Sqlite代码28“文件在打开时重命名”

    这是一个推论这个问题 https stackoverflow com questions 27784704 sqlite deadlock across multiple threads with different files nored

随机推荐