objective-c - Swift 中的故障安全断言

标签 objective-c swift macros

我通常在 Objective-C 中使用断言来声明一个值。在调试版本中,我断言以停止程序的执行并检查我的假设是否不正确。但是,在生产构建中,我找到了一种安全失败的方法,可以最大限度地减少对用户的影响。我通过创建一个宏来实现这一点,该宏将 NSAssert 封装在一个 if 语句中,该语句还执行我想在生产中作为故障安全运行的代码。例如:

我会使用的断言宏:

#define AssertTrueOrExecute(condition, action) \
  if (!condition) { \
    NSAssert(testCondition, @"Condition failed"); \
    action; \
  }

在我的应用程序的某个地方,我会有这样的东西:

- (void)someMethod
{
  BOOL testCondition = ...
  // Ensure the testCondition is true before proceeding any further
  AssertTrueOrExecute(testCondition, return);
  // Potentially unsafe code that never gets executed if testCondition is false
}

- (void)someReturningMethod
{
  BOOL testCondition = ...
  // Ensure the testCondition is true before proceeding any further
  AssertTrueOrExecute(testCondition, return @"safe string");
  // Potentially unsafe code that never gets executed if testCondition is false
}

因为我不能像 Swift 中提到的那样定义一个宏,有没有办法有相同的行为?这就是我如何为我的 AssertTrueOrExecute 宏创建一个 Swift 等价物?

更新:

为了进一步解释这个问题,如果我使用的是 Swift,我目前会这样写:

func someMethod () {
    let testCondition : Bool = ...

    // Ensure the testCondition is true before proceeding any further
    if (!testCondition) {
      assert(testCondition);
      return;
    }
    // Potentially unsafe code that never gets executed if testCondition is false
}

所以问题更多的是如何以类似的方式包装带有断言的 if 语句,我有 Objective-C 宏,以便我可以断言或提前返回?

更新 2:

另一个例子是在函数中返回一些东西,例如:

func someReturningMethod () -> String {
    let testCondition : Bool = ...

    // Ensure the testCondition is true before proceeding any further
    if (!testCondition) {
      assert(testCondition);
      return "safe string";
    }    
    // Potentially unsafe code that never gets executed if testCondition is false
    return "some other string"
}

最佳答案

Swift 中没有宏,但在 Swift 中可能有其他方法可以实现与 Objective-C 中相同的功能。

然而,这里真正的问题是,您试图以一种您不应该的方式来解决问题:

不要混淆程序员错误运行时错误!

相反,明确区分什么是程序员错误 和什么是运行时错误。使用断言处理程序员错误,使用 NSError 处理运行时错误,分别在 Swift 中使用 try & catchthrow

请注意,程序员错误的“范围”并不局限于程序因断言失败而失败的程度:此类错误很可能具有不良副作用,使程序处于无效状态,而且通常是这样断言检测可能在断言失败之前很长时间内发生的错误。因此,当断言失败时,您的程序很可能已经处于无效状态。

根据经验,断言失败不应发生在生产代码中(阅读绝不能)。嗯,这些是程序员错误,应该修复,不是吗?您在单元测试中使用断言来验证您的假设。如果您仍然担心,您的假设可能会在生产中中断,并且还确定这不是运行时错误(应该始终妥善处理),那么它应该停止程序——无论如何,所有的赌注都没有了。在 Swift 中,您可以为此使用 fatalError

有时,违反特定假设是程序员错误还是运行时错误的区别并不总是那么明显,可能取决于上下文。不过,作为一名程序员,您始终可以定义它是什么。以字符串参数为例:如果您直接从想要创建帐户的用户输入的文本字段中获取它并询问他的姓名,您应该验证该字符串并在不适合时返回/抛出错误您的期望 - 例如,如果它是空的、太短等。也就是说,在 Swift 中,您可以抛出错误并在调用站点(可能在 View Controller 中)优雅地处理该错误。另一方面,您定义初始化User 对象的name 为空是没有意义的。也就是说,在您的 init 例程中,您定义有效用户名不能为空的先决条件,并使用 assertfatalError 进行检查.在这种情况下,当没有代码路径初始化名称为空的用户时,您的程序是正确的。

关于objective-c - Swift 中的故障安全断言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32639806/

相关文章:

ios - BUTTON SHAPE on in device (iPhone) setting result app crash if its off app working

ios - 在Swift中的 View Controller 之间传递数据(从TableView到DetailViewController)

c++ - 如何用模板函数替换宏?

c - ESP8266 硬件定时器,uS to ticks 奇怪的宏

c - 如何动态生成 C 类型?

objective-c - 奇怪的 NSData 输出

ios - Realm +地幔: how to avoid multiple inheritance duplication when integrating both frameworks?

ios - 如何从相机胶卷和照片库中选择多个视频?

ios - 将 NSLocalizedString 转换为 NSAttributedString 大写文本

swift - 如何显示 "Open in appstore"以在 swift 3 中通过通用链接(apple-app-site-association)进行安装?