快速的“前提条件”和“主张”之间的区别?


105

precondition(condition: Bool, message: String)assert(condition: Bool, message: String)Swift 和有什么不一样?

他们俩在我看来都一样。在哪种情况下,我们应该使用另一种?

Answers:


125

assert用于测试期间的健全性检查,而precondition用于防范可能发生的事情(如果发生),这意味着您的程序无法合理进行。

因此,例如,您可以assert对具有合理结果的计算(例如在一定范围内)进行计算,以快速发现是否有错误。但是,您不希望附带此功能,因为超出范围的结果可能是有效的,并且不是至关重要的,因此不应使您的应用程序崩溃(假设您只是使用它在进度栏中显示进度)。

另一方面,在获取元素时检查数组的下标是否有效是precondition。当请求无效的下标时,数组对象没有合理的下一步操作,因为它必须返回一个非可选值。

来自文档的全文(尝试单击assertprecondition在Xcode中单击):

前提

检查取得进步的必要条件。

使用此功能可以检测到即使在运输代码中也必须阻止程序继续运行的情况。

  • 在游乐场和-Onone构建中(Xcode的Debug配置的默认设置):如果condition评估为false,则在打印后以可调试状态停止程序执行message

  • 在-O构建中(Xcode的Release配置的默认设置):如果condition评估为false,则停止程序执行。

  • 在-Ounchecked的版本中,condition不会进行评估,但是优化器可能会假定它将评估为true。无法满足-Ounchecked构建中的假设是严重的编程错误。

断言

传统的C样式断言带有可选消息。

使用此功能可进行内部完整性检查,这些检查在测试过程中处于活动状态,但不会影响运输代码的性能。检查发行版本中的无效用法;见precondition

  • 在游乐场和-Onone构建中(Xcode的Debug配置的默认设置):如果condition评估为false,则在打印后以可调试状态停止程序执行message

  • 在-O构建中(Xcode的Release配置的默认设置), condition不进行评估,也没有任何影响。

  • 在-Ounchecked的版本中,condition不会进行评估,但是优化器可能会假定它将评估为true。无法满足-Ounchecked构建中的假设是严重的编程错误。


2
“但是,您不希望随身携带该软件,因为超出范围的结果可能是有效的,并且并不重要,因此不要使您的应用程序崩溃”,这对我来说很模糊。请您提供一个确切的例子吗?也许一些代码。
亲爱的

2
在回答您的问题时,我个人使用断言来捕获在编写和测试构建时本不应该发生的事情。想象一下一个保护语句data["name"],它读取不存在但应该存在的JSON 。在后卫中有一个断言..else {}可以使我崩溃并引起问题,从而帮助我捕获错误。同样,如果该代码正在生产中,则断言不会使程序崩溃,而我使用的任何备份代码(return nil)都将接管。
亚历克O

1
您不应该检查索引并且不做任何事情而不是使整个应用程序崩溃吗?
Iulian Onofrei

是的,您应该检查索引,但是每个人有时都会滑倒,并且使用断言可以帮助您意识到忘记了索引时应该检查索引。
维克多·恩格尔

“但是您不希望这样做,因为超出范围的结果可能是有效的,而且并不重要,因此不要使您的应用程序崩溃”。您可以根据需要提供任意数量的断言。Swift不会在发布应用程序的断言块中评估您的条件
Akshansh Thakur

90

我发现了Swift断言-缺少的手册很有帮助

                        debug   release   release
function                -Onone  -O       -Ounchecked
assert()                YES     NO        NO
assertionFailure()      YES     NO        NO**
precondition()          YES     YES       NO
preconditionFailure()   YES     YES       YES**
fatalError()*           YES     YES       YES

以及来自有关Swift Evolution的有趣讨论

–断言:检查您自己的代码是否存在内部错误

–前提条件:用于检查您的客户是否给了您有效的参数。

另外,您需要注意使用什么,请参见assertionFailure和Optimization Level


您能详细说明一下自己的代码和客户端的区别吗?对于客户端,您的意思是像在期望的String处插入数字一样?难道不应该通过简单的错误处理来解决?
亲爱的

@Honey我认为他的意思是关于网络API调用或客户端自己的插件的参数/结果。
陈李勇

客户将是使用您的代码的人,说您正在编写一个库,而程序员传递了无效的数据。您可能不想优雅地继续,因为这可能被认为是严重的编程错误。您可能永远都不应使无效的网络API数据崩溃,因为这对用户无济于事。
bompf

@ onmyway133:我认为从Xcode QuickHelp中precondition()preconditionFailure()它们具有相同的行为。这些函数之间的区别是:precondition在内部需要条件,而preconditionFailure只是抛出条件。
nahung89 '19

12

precondition当你船您的应用程序是在发布模式,所以你主动和先决条件未能应用程序将终止。 Assert默认情况下仅在调试模式下工作。

我在NSHipster上使用它时发现了一个很好的解释:

断言是从经典逻辑中借用的一个概念。在逻辑上,断言是关于证明内命题的陈述。在编程中,断言表示程序员在声明它们的地方对应用程序所做的假设。

当以前置条件和后置条件的形式使用时,它们描述了在方法或函数执行的开始和结束时对代码状态的期望,则断言形成合同。断言还可以用于在运行时强制执行条件,以防止在某些先决条件失败时执行。


可以使用编译器标志启用和禁用断言。它们可以在出厂代码中处于活动状态。
PéturIngi Egilsson

6

前提

func precondition(condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = default, file: StaticString = default, line: UWord = default)

检查取得进步的必要条件。

  1. 使用此功能可以检测到即使在运输代码中也必须阻止程序继续运行的情况。
  2. 在操场上,-Onone构建(Xcode的Debug配置的默认设置):如果条件评估为false,则在打印消息后以可调试状态停止程序执行。
  3. 在-O构建中(Xcode的Release配置的默认设置):如果条件评估为false,则停止程序执行。
  4. 在-Ounchecked构建中,不评估条件,但优化器可能会假定其评估为true。未能满足-Ounchecked构建中的假设是严重的编程错误。

断言

func assert(condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = default, file: StaticString = default, line: UWord = default)

传统的C样式断言带有可选消息。

  1. 使用此功能可进行内部完整性检查,这些检查在测试过程中处于活动状态,但不会影响运输代码的性能。检查发行版本中的无效用法;参见前提条件。

  2. 在操场上,-Onone构建(Xcode的Debug配置的默认设置):如果条件评估为false,则在打印消息后以可调试状态停止程序执行。

  3. 在-O构建中(Xcode的Release配置的默认设置),不评估条件,并且没有任何影响
  4. 在-Ounchecked构建中,不评估条件,但优化器可能会假定其评估为true。无法满足-Ounchecked构建中的假设是严重的编程错误

0

只是想加我的2美分。您可以根据需要在代码中添加任意多个断言。您可以使用这些断言发送代码。Swift不会为生产应用评估这些代码块。这些仅在调试模式下进行评估。

添加文档链接

还要附加来自swift.org的图像

在此处输入图片说明

另请注意,前提条件并非如此。如果前提条件未评估为真,则附带前提条件的代码将崩溃,并且应用程序将终止。

简而言之,断言用于调试,但可以在不影响生产的情况下进行传送。断言将在调试模式下评估,而不在生产环境下评估。

前提条件用于确保生产环境中不会发生意外情况。这些条件将被评估,并在评估为假的情况下终止您的应用

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.