Difference between "precondition" and "assert" in swift?
assert
is for sanity checks during testing, whereas precondition
is for guarding against things that, if they happen, would mean your program just could not reasonably proceed.
So for example, you might put an assert
on some calculation having sensible results (within some bounds, say), to quickly find if you have a bug. But you wouldn’t want to ship with that, since the out-of-bound result might be valid, and not critical so shouldn’t crash your app (suppose you were just using it to display progress in a progress bar).
On the other hand, checking that a subscript on an array is valid when fetching an element is a precondition
. There is no reasonable next action for the array object to take when asked for an invalid subscript, since it must return a non-optional value.
Full text from the docs (try option-clicking assert
and precondition
in Xcode):
Precondition
Check a necessary condition for making forward progress.
Use this function to detect conditions that must prevent the program from proceeding even in shipping code.
In playgrounds and -Onone builds (the default for Xcode's Debug configuration): if
condition
evaluates to false, stop program execution in a debuggable state after printingmessage
.In -O builds (the default for Xcode's Release configuration): if
condition
evaluates to false, stop program execution.In -Ounchecked builds,
condition
is not evaluated, but the optimizer may assume that it would evaluate totrue
. Failure to satisfy that assumption in -Ounchecked builds is a serious programming error.
Assert
Traditional C-style assert with an optional message.
Use this function for internal sanity checks that are active during testing but do not impact performance of shipping code. To check for invalid usage in Release builds; see
precondition
.
In playgrounds and -Onone builds (the default for Xcode's Debug configuration): if
condition
evaluates to false, stop program execution in a debuggable state after printingmessage
.In -O builds (the default for Xcode's Release configuration),
condition
is not evaluated, and there are no effects.In -Ounchecked builds,
condition
is not evaluated, but the optimizer may assume that it would evaluate totrue
. Failure to satisfy that assumption in -Ounchecked builds is a serious programming error.
precondition
func precondition(condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = default, file: StaticString = default, line: UWord = default)
Check a necessary condition for making forward progress.
- Use this function to detect conditions that must prevent the program from proceeding even in shipping code.
- In playgrounds and -Onone builds (the default for Xcode's Debug configuration): if condition evaluates to false, stop program execution in a debuggable state after printing message.
- In -O builds (the default for Xcode's Release configuration): if condition evaluates to false, stop program execution.
- In -Ounchecked builds, condition is not evaluated, but the optimizer may assume that it would evaluate to true. Failure to satisfy that assumption in -Ounchecked builds is a serious programming error.
assert
func assert(condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = default, file: StaticString = default, line: UWord = default)
Traditional C-style assert with an optional message.
Use this function for internal sanity checks that are active during testing but do not impact performance of shipping code. To check for invalid usage in Release builds; see precondition.
In playgrounds and -Onone builds (the default for Xcode's Debug configuration): if condition evaluates to false, stop program execution in a debuggable state after printing message.
- In -O builds (the default for Xcode's Release configuration), condition is not evaluated, and there are no effects
- In -Ounchecked builds, condition is not evaluated, but the optimizer may assume that it would evaluate to true. Failure to satisfy that assumption in -Ounchecked builds is a serious programming erro
I found Swift asserts - the missing manual to be helpful
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
And from Interesting discussions on Swift Evolution
– assert: checking your own code for internal errors
– precondition: for checking that your clients have given you valid arguments.
Also, you need to be careful on what to use, see assertionFailure and Optimization Level
The precondition
is active in release mode so you when you ship your app and the precondition failed the app will terminate.
Assert
works just in debug mode as default.
I found this great explanation when to use it on NSHipster:
Assertions are a concept borrowed from classical logic. In logic, assertions are statements about propositions within a proof. In programming, assertions denote assumptions the programmer has made about the application at the place where they are declared.
When used in the capacity of preconditions and postconditions, which describe expectations about the state of the code at the beginning and end of execution of a method or function, assertions form a contract. Assertions can also be used to enforce conditions at run-time, in order to prevent execution when certain preconditions fail.