Пять стоп-слов для вашего iOS-приложения

Чтобы лучше понять, когда их использовать, нужно рассмотреть уровни оптимизации (Swift Optimization Levels). Когда вы собираете свое приложение, компилятор выполняет оптимизацию вашего кода, чтобы сделать его более быстрым.
Вы можете использовать различные уровни оптимизации для различных конфигураций сборки:
1️⃣ -Onone. Предназначен для обычной разработки. Он выполняет минимальную оптимизацию и сохраняет всю отладочную информацию.
2️⃣ -O. Компилятор выполняет агрессивную оптимизацию, которая может радикально изменить и тип, и количество выпускаемого кода. Отладочная информация будет передаваться, но с потерями.
3️⃣ -Osize. Это специальный режим оптимизации, в котором компилятор отдает приоритет размеру кода, а не производительности.
Чтобы изменить уровень оптимизации, можно перейти в Build Settings -> Optimization Level.
Нам доступно пять вариантов остановки приложения, кроме exit() и abort().
assert
Это функция, которая принимает четыре параметра. Условие и сообщение — это те параметры, которые вы будете использовать. Номер файла и номер строки (последние два параметра) вам, скорее всего, не понадобятся. С помощью функции assert() вы оцениваете условие, и если оно false, ваше приложение будет остановлено. Условие будет оцениваться только для сборок -Onone. Другими словами, она будет работать только для отладочных билдов.
func printAge(_ age: Int) {
assert(age >= 0, "Age can't be a negative value")
print("Age is: ", age)
}
printAge(-1) // prints: assertion failed: Age can't be a negative value: file Assertions.playground, line 6
assertionFailure
Если у вас нет условия для оценки или вам не нужно его оценивать, вы можете использовать функцию assertionFailure(). Она принимает в качестве аргумента строку, которая будет выведена в качестве сообщения. Как и assert, эта функция вызывается только для сборок -Onone. Давайте изменим наш сложный пример, чтобы использовать assertionFailure:
func printAge(_ age: Int) {
guard age >= 0 else {
assertionFailure("Age can't be a negative value")
return
}
print("Age is: ", age)
}
printAge(-1) // prints: fatal error: Age can't be a negative value: file Assertions.playground, line 9
precondition
precondition() принимает те же параметры, что и assert(), и делает практически то же самое. Единственное отличие заключается в том, что precondition работает для сборок -Onone и -O. Другими словами, для стандартных конфигураций отладки и релиза. Вы будете использовать ее так же, как и assert:
func printAge(_ age: Int) {
precondition(age >= 0, "Age can't be a negative value")
print("Age is: ", age)
}
printAge(-1) // prints: precondition failed: Age can't be a negative value: file Assertions.playground, line 6
preconditionFailure
Вы видите, к чему все идет, верно? preconditionFailure() работает так же, как assertionFailure(). С той же разницей, что и выше, она работает для сборок -Onone и -O. Опять же, вы будете использовать его так же, как и assertionFailure:
func printAge(_ age: Int) {
guard age >= 0 else {
preconditionFailure("Age can't be a negative value")
}
print("Age is: ", age)
}
printAge(-1) // prints: fatal error: Age can't be a negative value: file Assertions.playground, line 9
Если вы внимательно посмотрите на сигнатуру метода этой функции, то увидите, что она имеет возвращаемый тип:
public func preconditionFailure(_ message: @autoclosure () -> String = default, file: StaticString = #file, line: UInt = #line) -> Never
Тип Never указывает, что эта функция никогда не вернется. Это остановит выполнение приложения.
fatalError
fatalError(), как и assertionFailure() и preconditionFailure(), принимает строку в качестве аргумента, которая будет напечатана в консоли перед завершением работы приложения. Он работает для всех уровней оптимизации во всех конфигурациях сборки. Вы используете его так же, как два других:
func printAge(_ age: Int) {
guard age >= 0 else {
fatalError("Age can't be a negative value")
}
print("Age is: ", age)
}
printAge(-1) // prints: fatal error: Age can't be a negative value: file Assertions.playground, line 9
И так же, как в preconditionFailure(), возвращаемый тип здесь также Never.
Когда их использовать и в каком количестве — тема не такая однозначная, как может показаться на первый взгляд. Но при разработке приложения каждый из перечисленных вариантов может быть полезен в той или иной степени.
А про разработку можно прочитать в моём авторском канале.
