title | description | ms.custom | ms.date | ms.prod | ms.reviewer | ms.suite | ms.tgt_pltfrm | ms.topic | ms.assetid | caps.latest.revision | author | ms.author | manager |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
SWIFT error codes in BizTalk Server | Microsoft Docs |
View the class and validation types for the SWIFT Accelerator in BizTalk Server |
08/16/2017 |
biztalk-server |
article |
03699986-965b-4a28-ab2e-09f110fb4db6 |
4 |
MandiOhlinger |
mandia |
anneta |
SWIFT defines many network-imposed validations against the set of financial (FIN) messages. Each validation relates to a type of check against the contents of the message, and is associated with a three-character error code. The first character of the error code implies the class of the problem detected, and is a letter. The remaining two characters denote the detail of the error (when combined with the class) and always appear as a two-digit code.
Class of errors
The following table lists the letter designations, validation type, rule change associated with each class of error, and whether or not the class of error is supported.
Class | Validation type and rule change | Supported? |
---|---|---|
C, D, E | Semantic validation rules 0-299 | Supported |
Knn | Invalid code word in field nn | Supported |
M50 | Message length exceeded | Unsupported |
M60 | Non-SWIFT character encountered | Supported |
T | Text validation error codes | Supported |
G | Specific error codes for message user group (MUG) Textval rules | Unsupported |
B | Special error codes for value-added services | Unsupported |
All SWIFT errors should be referenced in the SWIFT User Handbook. For more information and for a complete list of SWIFT error codes, refer to the Message Format Validation Rules volume of the SWIFT User Handbook. [!INCLUDEbtaA4SWIFT2.3abbrevnonumber] implements the rules in the September 2003 edition of this publication. You can access the SWIFT Web site at https://go.microsoft.com/fwlink/?LinkId=27885.
Validation errors
There are some codes which are defined by A4SWIFT. These error codes are used in the validation/network rules created and implemented by A4SWIFT, so there is no corresponding error code defined by SWIFT for such rules. Below table shows the error code and corresponding case in which the error is thrown. is the particular field which throws the error.
Error Code | Description |
---|---|
A4SWIFT001 | The first character of multiline field cannot be ‘:’ or ‘-‘ character for second and subsequent lines. |
A4SWIFT002 | Field contains invalid value. |
[!NOTE]
[!INCLUDEA4SWIFT_CurrentVersion_FirstRef] includes support for some legacy messages, because internal applications might use these messages. Therefore, A4SWIFT maintains the associated SWIFT rules and error codes.
More good info
Troubleshooting: Issues and Resolutions
Known Issues
Common terms and definitions
title | description | ms.custom | ms.date | ms.prod | ms.reviewer | ms.suite | ms.tgt_pltfrm | ms.topic | ms.assetid | caps.latest.revision | author | ms.author | manager |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
SWIFT error codes in BizTalk Server | Microsoft Docs |
View the class and validation types for the SWIFT Accelerator in BizTalk Server |
08/16/2017 |
biztalk-server |
article |
03699986-965b-4a28-ab2e-09f110fb4db6 |
4 |
MandiOhlinger |
mandia |
anneta |
SWIFT defines many network-imposed validations against the set of financial (FIN) messages. Each validation relates to a type of check against the contents of the message, and is associated with a three-character error code. The first character of the error code implies the class of the problem detected, and is a letter. The remaining two characters denote the detail of the error (when combined with the class) and always appear as a two-digit code.
Class of errors
The following table lists the letter designations, validation type, rule change associated with each class of error, and whether or not the class of error is supported.
Class | Validation type and rule change | Supported? |
---|---|---|
C, D, E | Semantic validation rules 0-299 | Supported |
Knn | Invalid code word in field nn | Supported |
M50 | Message length exceeded | Unsupported |
M60 | Non-SWIFT character encountered | Supported |
T | Text validation error codes | Supported |
G | Specific error codes for message user group (MUG) Textval rules | Unsupported |
B | Special error codes for value-added services | Unsupported |
All SWIFT errors should be referenced in the SWIFT User Handbook. For more information and for a complete list of SWIFT error codes, refer to the Message Format Validation Rules volume of the SWIFT User Handbook. [!INCLUDEbtaA4SWIFT2.3abbrevnonumber] implements the rules in the September 2003 edition of this publication. You can access the SWIFT Web site at https://go.microsoft.com/fwlink/?LinkId=27885.
Validation errors
There are some codes which are defined by A4SWIFT. These error codes are used in the validation/network rules created and implemented by A4SWIFT, so there is no corresponding error code defined by SWIFT for such rules. Below table shows the error code and corresponding case in which the error is thrown. is the particular field which throws the error.
Error Code | Description |
---|---|
A4SWIFT001 | The first character of multiline field cannot be ‘:’ or ‘-‘ character for second and subsequent lines. |
A4SWIFT002 | Field contains invalid value. |
[!NOTE]
[!INCLUDEA4SWIFT_CurrentVersion_FirstRef] includes support for some legacy messages, because internal applications might use these messages. Therefore, A4SWIFT maintains the associated SWIFT rules and error codes.
More good info
Troubleshooting: Issues and Resolutions
Known Issues
Common terms and definitions
Обработка ошибок
Обработка ошибок — это процесс реагирования на возникновение ошибок и восстановление после появления ошибок в программе. Swift предоставляет первоклассную поддержку при генерации, вылавливании и переносе ошибок, устранении ошибок во время выполнения программы.
Некоторые операции не всегда гарантируют полное выполнение или конечный результат. Опционалы используются для обозначения отсутствия значения, но когда случается сбой, важно понять, что вызвало сбой, для того, чтобы соответствующим образом изменить код.
В качестве примера, рассмотрим задачу считывания и обработки данных из файла на диске. Задача может провалиться по нескольким причинам, в том числе: файл не существует по указанному пути, или файл не имеет разрешение на чтение, или файл не закодирован в необходимом формате. Отличительные особенности этих различных ситуаций позволяют программе решать некоторые ошибки самостоятельно и сообщать пользователю какие ошибки она не может решить сама.
Отображение и генерация ошибок
В Swift ошибки отображаются значениями типов, которые соответствуют протоколу Error. Этот пустой протокол является индикатором того, что это перечисление может быть использовано для обработки ошибок.
Перечисления в Swift особенно хорошо подходят для группировки схожих между собой условий возникновения ошибок и соответствующих им значений, что позволяет получить дополнительную информацию о природе самой ошибки. Например, вот как отображаются условия ошибки работы торгового автомата внутри игры:
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
Генерация ошибки позволяет указать, что произошло что-то неожиданное и обычное выполнение программы не может продолжаться. Для того чтобы «сгенерировать» ошибку, вы используете инструкцию throw. Например, следующий код генерирует ошибку, указывая, что пять дополнительных монет нужны торговому автомату:
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
Обработка ошибок
Когда генерируется ошибка, то фрагмент кода, окружающий ошибку, должен быть ответственным за ее обработку: например, он должен исправить ее, или испробовать альтернативный подход, или просто информировать пользователя о неудачном исполнении кода.
В Swift существует четыре способа обработки ошибок. Вы можете передать (propagate) ошибку из функции в код, который вызывает саму эту функцию, обработать ошибку, используя инструкцию do-catch, обработать ошибку, как значение опционала, или можно поставить утверждение, что ошибка в данном случае исключена. Каждый вариант будет рассмотрен далее.
Когда функция генерирует ошибку, последовательность выполнения вашей программы меняется, поэтому важно сразу обнаружить место в коде, которое может генерировать ошибки. Для того, чтобы выяснить где именно это происходит, напишите ключевое слово try — или варианты try? или try!— до куска кода, вызывающего функцию, метод или инициализатор, который может генерировать ошибку. Эти ключевые слова описываются в следующем параграфе.
Заметка
Обработка ошибок в Swift напоминает обработку исключений (exceptions) в других языках, с использованием ключевых слов try, catch и throw. В отличие от обработки исключений во многих языках, в том числе и в Objective-C- обработка ошибок в Swift не включает разворачивание стека вызовов, то есть процесса, который может быть дорогим в вычислительном отношении. Таким образом, производительные характеристики инструкции throw сопоставимы с характеристиками оператора return.
Передача ошибки с помощью генерирующей функции
Чтобы указать, что функция, метод или инициализатор могут генерировать ошибку, вам нужно написать ключевое слово throws в реализации функции после ее параметров. Функция, отмеченная throws называется генерирующей функцией. Если у функции установлен возвращаемый тип, то вы пишете ключевое слово throws перед стрелкой возврата (->).
func canThrowErrors() throws -> String
func cannotThrowErrors() -> String
Генерирующая функция передает ошибки, которые возникают внутри нее в область вызова этой функции.
Заметка
Только генерирующая ошибку функция может передавать ошибки. Любые ошибки, сгенерированные внутри non-throwing функции, должны быть обработаны внутри самой функции.
В приведенном ниже примере VendingMachine класс имеет vend(itemNamed: ) метод, который генерирует соответствующую VendingMachineError, если запрошенный элемент недоступен, его нет в наличии, или имеет стоимость, превышающую текущий депозит:
struct Item {
var price: Int
var count: Int
}
class VendingMachine {
var inventory = [
"Candy Bar": Item(price: 12, count: 7),
"Chips": Item(price: 10, count: 4),
"Pretzels": Item(price: 7, count: 11)
]
var coinsDeposited = 0
func vend(itemNamed name: String) throws {
guard let item = inventory[name] else {
throw VendingMachineError.invalidSelection
}
guard item.count > 0 else {
throw VendingMachineError.outOfStock
}
guard item.price <= coinsDeposited else {
throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
}
coinsDeposited -= item.price
var newItem = item
newItem.count -= 1
inventory[name] = newItem
print("Dispensing (name)")
}
}
Реализация vend(itemNamed: ) метода использует оператор guard для раннего выхода из метода и генерации соответствующих ошибок, если какое-либо требование для приобретения закуски не будет выполнено. Потому что инструкция throw мгновенно изменяет управление программой, и выбранная позиция будет куплена, только если все эти требования будут выполнены.
Поскольку vend(itemNamed: ) метод передает все ошибки, которые он генерирует, вызывающему его коду, то они должны быть обработаны напрямую, используя оператор do-catch, try? или try!, или должны быть переданы дальше. Например, buyFavoriteSnack(person:vendingMachine: ) в примере ниже — это тоже генерирующая функция, и любые ошибки, которые генерирует метод vend(itemNamed: ), будут переноситься до точки, где будет вызываться функция buyFavoriteSnack(person:vendingMachine: ).
let favoriteSnacks = [
"Alice": "Chips",
"Bob": "Licorice",
"Eve": "Pretzels"
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
try vendingMachine.vend(itemNamed: snackName)
}
В этом примере, функция buyFavoriteSnack(person:vendingMachine: ) подбирает любимые закуски данного человека и пытается их купить, вызывая vend(itemNamed: ) метод. Поскольку метод vend(itemNamed: ) может сгенерировать ошибку, он вызывается с ключевым словом try перед ним.
Генерирующие ошибку инициализаторы могут распространять ошибки таким же образом, как генерирующие ошибку функции. Например, инициализатор структуры PurchasedSnack в списке ниже вызывает генерирующую ошибку функции как часть процесса инициализации, и он обрабатывает любые ошибки, с которыми сталкивается, путем распространения их до вызывающего его объекта.
struct PurchasedSnack {
let name: String
init(name: String, vendingMachine: VendingMachine) throws {
try vendingMachine.vend(itemNamed: name)
self.name = name
}
}
Обработка ошибок с использованием do-catch
Используйте инструкцию do-catch для обработки ошибок, запуская блок кода. Если выдается ошибка в коде условия do, она соотносится с условием catch для определения того, кто именно сможет обработать ошибку.
Вот общий вид условия do-catch:
do {
try выражение
выражение
} catch шаблон 1 {
выражение
} catch шаблон 2 where условие {
выражение
} catch шаблон 3, шаблон 4 where условие {
выражение
} catch {
выражение
}
Вы пишете шаблон после ключевого слова catch, чтобы указать какие ошибки могут обрабатываться данным пунктом этого обработчика. Если условие catch не имеет своего шаблона, то оно подходит под любые ошибки и связывает ошибки к локальной константе error. Более подробно о соответствии шаблону см. Шаблоны.
Например, следующий код обрабатывает все три случая в перечислении VendingMachineError, но все другие ошибки должны быть обработаны окружающей областью:
var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
} catch VendingMachineError.invalidSelection {
print("Ошибка выбора.")
} catch VendingMachineError.outOfStock {
print("Нет в наличии.")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
print("Недостаточно средств. Пожалуйста вставьте еще (coinsNeeded) монетки.")
} catch {
print("Неожиданная ошибка: (error).")
}
// Выведет "Недостаточно средств. Пожалуйста вставьте еще 2 монетки.
В приведенном выше примере, buyFavoriteSnack(person:vendingMachine: ) функция вызывается в выражении try, потому что она может сгенерировать ошибку. Если генерируется ошибка, выполнение немедленно переносится в условия catch, которые принимают решение о продолжении передачи ошибки. Если ошибка не генерируется, остальные операторы do выполняются.
В условии catch не нужно обрабатывать все возможные ошибки, которые может вызвать код в условии do. Если ни одно из условий catch не обрабатывает ошибку, ошибка распространяется на окружающую область. Однако распространяемая ошибка должна обрабатываться некоторой внешней областью. В функции nonthrowing условие включения do-catch должно обрабатывать ошибку. В функции throwing либо включающая условие do-catch, либо вызывающая сторона должна обрабатывать ошибку. Если ошибка распространяется на область верхнего уровня без обработки, вы получите ошибку исполнения.
Например, приведенный ниже пример можно записать так, чтобы любая ошибка, которая не является VendingMachineError, вместо этого захватывалась вызывающей функцией:
func nourish(with item: String) throws {
do {
try vendingMachine.vend(itemNamed: item)
} catch is VendingMachineError {
print("Некорректный вывод, нет в наличии или недостаточно денег.")
}
}
do {
try nourish(with: "Beet-Flavored Chips")
} catch {
print("Unexpected non-vending-machine-related error: (error)")
}
// Выведет "Некорректный вывод, нет в наличии или недостаточно денег."
В nourish(with: ), если vend(itemNamed : ) выдает ошибку, которая является одним из кейсов перечисления VendingMachineError, nourish(with: ) обрабатывает ошибку, печатая сообщение. В противном случае, nourish(with: ) распространяет ошибку на свое место вызова. Ошибка затем попадает в общее условие catch.
Преобразование ошибок в опциональные значения
Вы можете использовать try? для обработки ошибки, преобразовав ее в опциональное значение. Если ошибка генерируется при условии try?, то значение выражения вычисляется как nil. Например, в следующем коде x и y имеют одинаковые значения и поведение:
func someThrowingFunction() throws -> Int {
// ...
}
let x = try? someThrowingFunction()
let y: Int?
do {
y = try someThrowingFunction()
} catch {
y = nil
}
Если someThrowingFunction() генерирует ошибку, значение x и y равно nil. В противном случае значение x и y — это возвращаемое значение функции. Обратите внимание, что x и y являются опциональными, независимо от того какой тип возвращает функция someThrowingFunction().
Использование try? позволяет написать краткий код обработки ошибок, если вы хотите обрабатывать все ошибки таким же образом. Например, следующий код использует несколько попыток для извлечения данных или возвращает nil, если попытки неудачные.
func fetchData() -> Data? {
if let data = try? fetchDataFromDisk() { return data }
if let data = try? fetchDataFromServer() { return data }
return nil
}
Запрет на передачу ошибок
Иногда вы знаете, что функции throw или методы не сгенерируют ошибку во время исполнения. В этих случаях, вы можете написать try! перед выражением для запрета передачи ошибки и завернуть вызов в утверждение того, что ошибка точно не будет сгенерирована. Если ошибка на самом деле сгенерирована, вы получите сообщение об ошибке исполнения.
Например, следующий код использует loadImage(atPath: ) функцию, которая загружает ресурс изображения по заданному пути или генерирует ошибку, если изображение не может быть загружено. В этом случае, поскольку изображение идет вместе с приложением, сообщение об ошибке не будет сгенерировано во время выполнения, поэтому целесообразно отключить передачу ошибки.
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
Установка действий по очистке (Cleanup)
Вы используете оператор defer для выполнения набора инструкций перед тем как исполнение кода оставит текущий блок. Это позволяет сделать любую необходимую очистку, которая должна быть выполнена, независимо от того, как именно это произойдет — либо он покинет из-за сгенерированной ошибки или из-за оператора, такого как break или return. Например, вы можете использовать defer, чтобы удостовериться, что файл дескрипторов закрыт и выделенная память вручную освобождена.
Оператор defer откладывает выполнение, пока не происходит выход из текущей области. Этот оператор состоит из ключевого слова defer и выражений, которые должны быть выполнены позже. Отложенные выражения могут не содержать кода, изменяющего контроль исполнения изнутри наружу, при помощи таких операторов как break или return, или просто генерирующего ошибку. Отложенные действия выполняются в обратном порядке, как они указаны, то есть, код в первом операторе defer выполняется после кода второго, и так далее.
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
defer {
close(file)
}
while let line = try file.readline() {
// работаем с файлом.
}
// close(file) вызывается здесь, в конце зоны видимости.
}
}
Приведенный выше пример использует оператор defer, чтобы удостовериться, что функция open(_: ) имеет соответствующий вызов и для close(_: ).
Заметка
Вы можете использовать оператор defer, даже если не используете кода обработки ошибок.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
Обработка ошибок — это процесс реагирования и исправления ошибок в вашей программе. Swift обеспечивает первоклассную поддержку для генерации, перехвата, распространения и обработки исправляемых ошибок во время выполнения.
Некоторые операции не всегда гарантируют завершение выполнения или получение полезного результата. Необязательные параметры используются для представления отсутствия значения, но когда происходит сбой операции, часто полезно понять, что вызвало сбой, чтобы ваш код мог реагировать соответствующим образом.
В качестве примера рассмотрим задачу чтения и обработки данных из файла на диске. Эта задача может быть выполнена несколькими способами, включая файл, не существующий по указанному пути, файл, не имеющий разрешений на чтение, или файл, не закодированный в совместимом формате. Различение между этими различными ситуациями позволяет программе устранять некоторые ошибки и сообщать пользователю о любых ошибках, которые она не может устранить.
ЗАМЕТКА
Обработка ошибок в Swift взаимодействует с шаблонами обработки ошибок, которые используют
NSError
класс в Какао и Objective-C.
Представление и бросание ошибок
В Swift ошибки представлены значениями типов, которые соответствуют Error
протоколу. Этот пустой протокол указывает, что тип может использоваться для обработки ошибок.
Перечисления Swift особенно хорошо подходят для моделирования группы связанных состояний ошибок с соответствующими значениями, позволяющими передавать дополнительную информацию о природе ошибки. Например, вот как вы можете представить условия ошибки работы торгового автомата в игре:
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
Выдача ошибки позволяет вам указать, что произошло что-то неожиданное, и нормальный поток выполнения не может продолжаться. Вы используете throw
заявление, чтобы выбросить ошибку. Например, следующий код выдает ошибку, чтобы указать, что торговому автомату необходимо пять дополнительных монет:
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
Обработка ошибок
Когда выдается ошибка, некоторый окружающий фрагмент кода должен отвечать за обработку ошибки — например, путем исправления проблемы, попытки альтернативного подхода или информирования пользователя о сбое.
Существует четыре способа обработки ошибок в Swift. Вы можете распространять ошибку из функции в код, который вызывает эту функцию, обрабатывать ошибку с помощью оператора do
— catch
, обрабатывать ошибку как необязательное значение или утверждать, что ошибка не произойдет. Каждый подход описан в разделе ниже.
Когда функция выдает ошибку, она меняет поток вашей программы, поэтому важно, чтобы вы могли быстро определить места в вашем коде, которые могут выдавать ошибки. Чтобы определить эти места в вашем коде, напишите try
ключевое слово ( try?
или try!
вариант или) перед фрагментом кода, который вызывает функцию, метод или инициализатор, который может вызвать ошибку. Эти ключевые слова описаны в разделах ниже.
ЗАМЕТКА
Обработка ошибок в Swift напоминает обработку исключений в других языках, с использованием
try
,catch
иthrow
ключевых слов. В отличие от обработки исключений во многих языках, включая Objective-C, обработка ошибок в Swift не включает в себя разматывание стека вызовов, процесс, который может быть вычислительно дорогим. Таким образом, рабочие характеристикиthrow
оператора сопоставимы с характеристикамиreturn
оператора.
Распространение ошибок с использованием бросающих функций
Чтобы указать, что функция, метод или инициализатор могут выдать ошибку, вы пишете throws
ключевое слово в объявлении функции после ее параметров. Функция с пометкой throws
называется функцией броска . Если функция указывает тип возвращаемого значения, вы пишете throws
ключевое слово перед стрелкой возврата ( ->
).
func canThrowErrors() throws -> String
func cannotThrowErrors() -> String
Функция выброса распространяет ошибки, которые выбрасываются внутри нее, в область, из которой она вызывается.
ЗАМЕТКА
Только бросающие функции могут распространять ошибки. Любые ошибки, возникающие в неработающей функции, должны обрабатываться внутри функции.
В приведенном ниже примере VendingMachine
класс имеет vend(itemNamed:)
метод, который выбрасывает соответствующее значение, VendingMachineError
если запрошенный элемент недоступен, отсутствует на складе или имеет стоимость, превышающую текущую сумму депозита:
struct Item {
var price: Int
var count: Int
}
class VendingMachine {
var inventory = [
"Candy Bar": Item(price: 12, count: 7),
"Chips": Item(price: 10, count: 4),
"Pretzels": Item(price: 7, count: 11)
]
var coinsDeposited = 0
func vend(itemNamed name: String) throws {
guard let item = inventory[name] else {
throw VendingMachineError.invalidSelection
}
guard item.count > 0 else {
throw VendingMachineError.outOfStock
}
guard item.price <= coinsDeposited else {
throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
}
coinsDeposited -= item.price
var newItem = item
newItem.count -= 1
inventory[name] = newItem
print("Dispensing (name)")
}
}
Реализация vend(itemNamed:)
метода использует guard
операторы для раннего выхода из метода и выдачи соответствующих ошибок, если какое-либо из требований для покупки закуски не выполнено. Поскольку throw
оператор немедленно передает управление программой, элемент будет продаваться, только если все эти требования будут выполнены.
Поскольку vend(itemNamed:)
метод распространяется любые ошибки , он бросает, любой код , который вызывает этот метод должен либо обрабатывать ошибки, используя do
— catch
заявление, try?
или try!
-или продолжают их распространять. Например, buyFavoriteSnack(person:vendingMachine:)
в приведенном ниже примере также есть функция throwing, и любые ошибки, которые vend(itemNamed:)
генерирует метод, будут распространяться вплоть до точки, где buyFavoriteSnack(person:vendingMachine:)
вызывается функция.
let favoriteSnacks = [
"Alice": "Chips",
"Bob": "Licorice",
"Eve": "Pretzels",
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
try vendingMachine.vend(itemNamed: snackName)
}
В этом примере функция ищет любимую закуску данного человека и пытается купить ее, вызвав метод. Поскольку метод может выдать ошибку, он вызывается с ключевым словом перед ним.buyFavoriteSnack(person: vendingMachine:)
vend(itemNamed:)
vend(itemNamed:)
try
Бросающие инициализаторы могут распространять ошибки так же, как и бросающие функции. Например, инициализатор для PurchasedSnack
структуры в приведенном ниже листинге вызывает функцию выброса как часть процесса инициализации и обрабатывает любые возникающие ошибки, передавая их вызывающей стороне.
struct PurchasedSnack {
let name: String
init(name: String, vendingMachine: VendingMachine) throws {
try vendingMachine.vend(itemNamed: name)
self.name = name
}
}
Обработка ошибок с помощью Do-Catch
Вы используете оператор do
— catch
для обработки ошибок, выполняя блок кода. Если код в do
предложении выдает ошибку , он сопоставляется с catch
предложениями, чтобы определить, какой из них может обработать ошибку.
Вот общая форма do
— catch
заявление:
do {
try expression
statements
} catch pattern 1 {
statements
} catch pattern 2 where condition {
statements
} catch {
statements
}
Вы пишете шаблон после, catch
чтобы указать, какие ошибки может обработать это предложение. Если catch
предложение не имеет шаблона, оно сопоставляется с любой ошибкой и связывает ошибку с локальной константой с именем error
.
Например, следующий код соответствует всем трем случаям VendingMachineError
перечисления.
var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
print("Success! Yum.")
} catch VendingMachineError.invalidSelection {
print("Invalid Selection.")
} catch VendingMachineError.outOfStock {
print("Out of Stock.")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
print("Insufficient funds. Please insert an additional (coinsNeeded) coins.")
} catch {
print("Unexpected error: (error).")
}
// Prints "Insufficient funds. Please insert an additional 2 coins."
В приведенном выше примере buyFavoriteSnack(person:vendingMachine:)
функция вызывается в try
выражении, поскольку она может выдать ошибку. Если выдается ошибка, выполнение немедленно переходит к catch
предложениям, которые решают, следует ли продолжить распространение. Если ни один шаблон не сопоставлен, ошибка попадает в заключительное catch
предложение и связывается с локальной error
константой. Если ошибка не выдана, остальные операторы в do
операторе выполняются.
Предложения catch
не должны обрабатывать каждую возможную ошибку, которую do
может выдать код в предложении. Если ни одно из catch
предложений не обрабатывает ошибку, ошибка распространяется на окружающую область. Однако распространяемая ошибка должна быть обработана некоторой окружающей областью. В функции nonthrowing, объемлющий do
— catch
пункт должен обработать ошибку. В функции метательного, либо вшита do
— catch
пункт или вызывающий должен обработать ошибку. Если ошибка распространяется на область верхнего уровня без обработки, вы получите ошибку во время выполнения.
Например, приведенный выше пример может быть написан так, что любая ошибка, которая не VendingMachineError
является, вместо этого перехватывается вызывающей функцией:
func nourish(with item: String) throws {
do {
try vendingMachine.vend(itemNamed: item)
} catch is VendingMachineError {
print("Invalid selection, out of stock, or not enough money.")
}
}
do {
try nourish(with: "Beet-Flavored Chips")
} catch {
print("Unexpected non-vending-machine-related error: (error)")
}
// Prints "Invalid selection, out of stock, or not enough money."
В nourish(with:)
функции, если vend(itemNamed:)
выдает ошибку, которая является одним из случаев VendingMachineError
перечисления, nourish(with:)
обрабатывает ошибку, печатая сообщение. В противном случае nourish(with:)
распространяет ошибку на свой сайт вызова. Ошибка тогда поймана общим catch
предложением.
Преобразование ошибок в необязательные значения
Вы используете try?
для обработки ошибки путем преобразования ее в необязательное значение. Если при вычислении try?
выражения выдается ошибка , значением выражения является nil
. Например, в следующем коде x
и y
имеют то же значение и поведение:
func someThrowingFunction() throws -> Int {
// ...
}
let x = try? someThrowingFunction()
let y: Int?
do {
y = try someThrowingFunction()
} catch {
y = nil
}
Если someThrowingFunction()
выдает ошибку, значение x
и y
есть nil
. В противном случае значение x
и y
является значением, которое вернула функция. Обратите внимание, что x
и y
являются необязательными для любого типа someThrowingFunction()
возврата. Здесь функция возвращает целое число, поэтому x
и y
являются необязательными целыми числами.
Использование try?
позволяет вам написать краткий код обработки ошибок, когда вы хотите обрабатывать все ошибки одинаково. Например, следующий код использует несколько подходов для извлечения данных или возвращает, nil
если все подходы дают сбой.
func fetchData() -> Data? {
if let data = try? fetchDataFromDisk() { return data }
if let data = try? fetchDataFromServer() { return data }
return nil
}
Отключение распространения ошибок
Иногда вы знаете, что бросающая функция или метод на самом деле не будут выдавать ошибку во время выполнения. В таких случаях вы можете написать try!
перед выражением, чтобы отключить распространение ошибок, и обернуть вызов в утверждение времени выполнения, что не будет выдано никакой ошибки. Если на самом деле выдается ошибка, вы получите ошибку во время выполнения.
Например, в следующем коде используется loadImage(atPath:)
функция, которая загружает ресурс изображения по заданному пути или выдает ошибку, если изображение не может быть загружено. В этом случае, поскольку образ поставляется с приложением, во время выполнения не будет выдано никаких ошибок, поэтому целесообразно отключить распространение ошибок.
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
Указание действий по очистке
Вы используете defer
оператор для выполнения набора операторов непосредственно перед тем, как выполнение кода покидает текущий блок кода. Этот оператор позволяет выполнять любую необходимую очистку, которая должна выполняться независимо от того, как выполнение покидает текущий блок кода — независимо от того, была ли вызвана ошибка или из-за оператора, такого как return
или break
. Например, вы можете использовать defer
инструкцию, чтобы гарантировать, что файловые дескрипторы закрыты, а выделенная вручную память освобождена.
defer
Заявление отсрочивает выполнение , пока текущая область не закрывается. Этот оператор состоит из defer
ключевого слова и операторов, которые будут выполнены позже. Отложенные операторы могут не содержать какой-либо код, который передавал бы управление из операторов, таких как оператор a break
или return
, или путем выдачи ошибки. Отложенные действия выполняются в порядке, обратном порядку их написания в исходном коде. То есть код в первом defer
операторе выполняется последним, код во втором defer
операторе выполняется со второго до последнего и так далее. Последний defer
оператор в порядке исходного кода выполняется первым.
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
defer {
close(file)
}
while let line = try file.readline() {
// Work with the file.
}
// close(file) is called here, at the end of the scope.
}
}
В приведенном выше примере используется defer
оператор, чтобы гарантировать, что open(_:)
функция имеет соответствующий вызов close(_:)
.
ЗАМЕТКА
Вы можете использовать
defer
оператор, даже если код обработки ошибок не используется.
Error handling is the process of responding to and recovering from error conditions in your program. Swift provides first-class support for throwing, catching, propagating, and manipulating recoverable errors at runtime.
Some operations aren’t guaranteed to always complete execution or produce a useful output. Optionals are used to represent the absence of a value, but when an operation fails, it’s often useful to understand what caused the failure, so that your code can respond accordingly.
As an example, consider the task of reading and processing data from a file on disk. There are a number of ways this task can fail, including the file not existing at the specified path, the file not having read permissions, or the file not being encoded in a compatible format. Distinguishing among these different situations allows a program to resolve some errors and to communicate to the user any errors it can’t resolve.
Representing and Throwing Errors¶
In Swift, errors are represented by values of types that conform to the Error
protocol. This empty protocol indicates that a type can be used for error handling.
Swift enumerations are particularly well suited to modeling a group of related error conditions, with associated values allowing for additional information about the nature of an error to be communicated. For example, here’s how you might represent the error conditions of operating a vending machine inside a game:
- enum VendingMachineError: Error {
- case invalidSelection
- case insufficientFunds(coinsNeeded: Int)
- case outOfStock
- }
Throwing an error lets you indicate that something unexpected happened and the normal flow of execution can’t continue. You use a throw
statement to throw an error. For example, the following code throws an error to indicate that five additional coins are needed by the vending machine:
- throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
Handling Errors¶
When an error is thrown, some surrounding piece of code must be responsible for handling the error—for example, by correcting the problem, trying an alternative approach, or informing the user of the failure.
There are four ways to handle errors in Swift. You can propagate the error from a function to the code that calls that function, handle the error using a do
—catch
statement, handle the error as an optional value, or assert that the error will not occur. Each approach is described in a section below.
When a function throws an error, it changes the flow of your program, so it’s important that you can quickly identify places in your code that can throw errors. To identify these places in your code, write the try
keyword—or the try?
or try!
variation—before a piece of code that calls a function, method, or initializer that can throw an error. These keywords are described in the sections below.
Note
Error handling in Swift resembles exception handling in other languages, with the use of the try
, catch
and throw
keywords. Unlike exception handling in many languages—including Objective-C—error handling in Swift doesn’t involve unwinding the call stack, a process that can be computationally expensive. As such, the performance characteristics of a throw
statement are comparable to those of a return
statement.
Propagating Errors Using Throwing Functions¶
To indicate that a function, method, or initializer can throw an error, you write the throws
keyword in the function’s declaration after its parameters. A function marked with throws
is called a throwing function. If the function specifies a return type, you write the throws
keyword before the return arrow (->
).
- func canThrowErrors() throws -> String
- func cannotThrowErrors() -> String
A throwing function propagates errors that are thrown inside of it to the scope from which it’s called.
Note
Only throwing functions can propagate errors. Any errors thrown inside a nonthrowing function must be handled inside the function.
In the example below, the VendingMachine
class has a vend(itemNamed:)
method that throws an appropriate VendingMachineError
if the requested item isn’t available, is out of stock, or has a cost that exceeds the current deposited amount:
- struct Item {
- var price: Int
- var count: Int
- }
- class VendingMachine {
- var inventory = [
- «Candy Bar»: Item(price: 12, count: 7),
- «Chips»: Item(price: 10, count: 4),
- «Pretzels»: Item(price: 7, count: 11)
- ]
- var coinsDeposited = 0
- func vend(itemNamed name: String) throws {
- guard let item = inventory[name] else {
- throw VendingMachineError.invalidSelection
- }
- guard item.count > 0 else {
- throw VendingMachineError.outOfStock
- }
- guard item.price <= coinsDeposited else {
- throw VendingMachineError.insufficientFunds(coinsNeeded: item.price — coinsDeposited)
- }
- coinsDeposited -= item.price
- var newItem = item
- newItem.count -= 1
- inventory[name] = newItem
- print(«Dispensing (name)«)
- }
- }
The implementation of the vend(itemNamed:)
method uses guard
statements to exit the method early and throw appropriate errors if any of the requirements for purchasing a snack aren’t met. Because a throw
statement immediately transfers program control, an item will be vended only if all of these requirements are met.
Because the vend(itemNamed:)
method propagates any errors it throws, any code that calls this method must either handle the errors—using a do
—catch
statement, try?
, or try!
—or continue to propagate them. For example, the buyFavoriteSnack(person:vendingMachine:)
in the example below is also a throwing function, and any errors that the vend(itemNamed:)
method throws will propagate up to the point where the buyFavoriteSnack(person:vendingMachine:)
function is called.
- let favoriteSnacks = [
- «Alice»: «Chips»,
- «Bob»: «Licorice»,
- «Eve»: «Pretzels»,
- ]
- func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
- let snackName = favoriteSnacks[person] ?? «Candy Bar»
- try vendingMachine.vend(itemNamed: snackName)
- }
In this example, the buyFavoriteSnack(person: vendingMachine:)
function looks up a given person’s favorite snack and tries to buy it for them by calling the vend(itemNamed:)
method. Because the vend(itemNamed:)
method can throw an error, it’s called with the try
keyword in front of it.
Throwing initializers can propagate errors in the same way as throwing functions. For example, the initializer for the PurchasedSnack
structure in the listing below calls a throwing function as part of the initialization process, and it handles any errors that it encounters by propagating them to its caller.
- struct PurchasedSnack {
- let name: String
- init(name: String, vendingMachine: VendingMachine) throws {
- try vendingMachine.vend(itemNamed: name)
- self.name = name
- }
- }
Handling Errors Using Do-Catch¶
You use a do
—catch
statement to handle errors by running a block of code. If an error is thrown by the code in the do
clause, it’s matched against the catch
clauses to determine which one of them can handle the error.
Here is the general form of a do
—catch
statement:
- do {
- try expression
- statements
- } catch pattern 1 {
- statements
- } catch pattern 2 where condition {
- statements
- } catch pattern 3, pattern 4 where condition {
- statements
- } catch {
- statements
- }
You write a pattern after catch
to indicate what errors that clause can handle. If a catch
clause doesn’t have a pattern, the clause matches any error and binds the error to a local constant named error
. For more information about pattern matching, see Patterns.
For example, the following code matches against all three cases of the VendingMachineError
enumeration.
- var vendingMachine = VendingMachine()
- vendingMachine.coinsDeposited = 8
- do {
- try buyFavoriteSnack(person: «Alice», vendingMachine: vendingMachine)
- print(«Success! Yum.»)
- } catch VendingMachineError.invalidSelection {
- print(«Invalid Selection.»)
- } catch VendingMachineError.outOfStock {
- print(«Out of Stock.»)
- } catch VendingMachineError.insufficientFunds(let coinsNeeded) {
- print(«Insufficient funds. Please insert an additional (coinsNeeded) coins.»)
- } catch {
- print(«Unexpected error: (error).»)
- }
- // Prints «Insufficient funds. Please insert an additional 2 coins.»
In the above example, the buyFavoriteSnack(person:vendingMachine:)
function is called in a try
expression, because it can throw an error. If an error is thrown, execution immediately transfers to the catch
clauses, which decide whether to allow propagation to continue. If no pattern is matched, the error gets caught by the final catch
clause and is bound to a local error
constant. If no error is thrown, the remaining statements in the do
statement are executed.
The catch
clauses don’t have to handle every possible error that the code in the do
clause can throw. If none of the catch
clauses handle the error, the error propagates to the surrounding scope. However, the propagated error must be handled by some surrounding scope. In a nonthrowing function, an enclosing do
—catch
statement must handle the error. In a throwing function, either an enclosing do
—catch
statement or the caller must handle the error. If the error propagates to the top-level scope without being handled, you’ll get a runtime error.
For example, the above example can be written so any error that isn’t a VendingMachineError
is instead caught by the calling function:
- func nourish(with item: String) throws {
- do {
- try vendingMachine.vend(itemNamed: item)
- } catch is VendingMachineError {
- print(«Couldn’t buy that from the vending machine.»)
- }
- }
- do {
- try nourish(with: «Beet-Flavored Chips»)
- } catch {
- print(«Unexpected non-vending-machine-related error: (error)«)
- }
- // Prints «Couldn’t buy that from the vending machine.»
In the nourish(with:)
function, if vend(itemNamed:)
throws an error that’s one of the cases of the VendingMachineError
enumeration, nourish(with:)
handles the error by printing a message. Otherwise, nourish(with:)
propagates the error to its call site. The error is then caught by the general catch
clause.
Another way to catch several related errors is to list them after catch
, separated by commas. For example:
- func eat(item: String) throws {
- do {
- try vendingMachine.vend(itemNamed: item)
- } catch VendingMachineError.invalidSelection, VendingMachineError.insufficientFunds, VendingMachineError.outOfStock {
- print(«Invalid selection, out of stock, or not enough money.»)
- }
- }
The eat(item:)
function lists the vending machine errors to catch, and its error text corresponds to the items in that list. If any of the three listed errors are thrown, this catch
clause handles them by printing a message. Any other errors are propagated to the surrounding scope, including any vending-machine errors that might be added later.
Converting Errors to Optional Values¶
You use try?
to handle an error by converting it to an optional value. If an error is thrown while evaluating the try?
expression, the value of the expression is nil
. For example, in the following code x
and y
have the same value and behavior:
- func someThrowingFunction() throws -> Int {
- // …
- }
- let x = try? someThrowingFunction()
- let y: Int?
- do {
- y = try someThrowingFunction()
- } catch {
- y = nil
- }
If someThrowingFunction()
throws an error, the value of x
and y
is nil
. Otherwise, the value of x
and y
is the value that the function returned. Note that x
and y
are an optional of whatever type someThrowingFunction()
returns. Here the function returns an integer, so x
and y
are optional integers.
Using try?
lets you write concise error handling code when you want to handle all errors in the same way. For example, the following code uses several approaches to fetch data, or returns nil
if all of the approaches fail.
- func fetchData() -> Data? {
- if let data = try? fetchDataFromDisk() { return data }
- if let data = try? fetchDataFromServer() { return data }
- return nil
- }
Disabling Error Propagation¶
Sometimes you know a throwing function or method won’t, in fact, throw an error at runtime. On those occasions, you can write try!
before the expression to disable error propagation and wrap the call in a runtime assertion that no error will be thrown. If an error actually is thrown, you’ll get a runtime error.
For example, the following code uses a loadImage(atPath:)
function, which loads the image resource at a given path or throws an error if the image can’t be loaded. In this case, because the image is shipped with the application, no error will be thrown at runtime, so it’s appropriate to disable error propagation.
- let photo = try! loadImage(atPath: «./Resources/John Appleseed.jpg»)
Specifying Cleanup Actions¶
You use a defer
statement to execute a set of statements just before code execution leaves the current block of code. This statement lets you do any necessary cleanup that should be performed regardless of how execution leaves the current block of code—whether it leaves because an error was thrown or because of a statement such as return
or break
. For example, you can use a defer
statement to ensure that file descriptors are closed and manually allocated memory is freed.
A defer
statement defers execution until the current scope is exited. This statement consists of the defer
keyword and the statements to be executed later. The deferred statements may not contain any code that would transfer control out of the statements, such as a break
or a return
statement, or by throwing an error. Deferred actions are executed in the reverse of the order that they’re written in your source code. That is, the code in the first defer
statement executes last, the code in the second defer
statement executes second to last, and so on. The last defer
statement in source code order executes first.
- func processFile(filename: String) throws {
- if exists(filename) {
- let file = open(filename)
- defer {
- close(file)
- }
- while let line = try file.readline() {
- // Work with the file.
- }
- // close(file) is called here, at the end of the scope.
- }
- }
The above example uses a defer
statement to ensure that the open(_:)
function has a corresponding call to close(_:)
.
Note
You can use a defer
statement even when no error handling code is involved.
Мы используем обработку ошибок с помощью do-try-catch для реагирования на исправимые ошибки. Это дает нам больший контроль над различными ошибочными сценариями, которые могут возникнуть в нашем коде, например, при вводе неправильного имени пользователя или пароля.
Зачем нужно отслеживать ошибки?
В приложении некоторые ошибки могут быть результатом ошибок программиста. Когда ваше приложение вылетает с сообщением «Index out of bounds», вы, вероятно, где-то допустили ошибку. И точно так же, когда вы принудительно извлекаете опциональное значение, которое имеет значение nil, ваше приложение падает.
В практической разработке iOS некоторые ошибки являются частью работы приложения, например, сообщение «Недостаточно средств» при попытке оплаты с помощью карты.
Ошибки такого рода исправимы. Их можно обработать и отреагировать соответствующим образом. К примеру:
- При попытке снять деньги в банкомате отображается «Неверный PIN-код».
- Ваш автомобиль показывает индикатор низкого уровня топлива при попытке запустить двигатель.
- Попытка аутентификации для API возвращает «Неверное имя пользователя / пароль».
Вы можете работать с этими ошибками, отобразив сообщение с предупреждением или сделав что-то еще. Например, ваша карта блокируется после 3 неудачных попыток. Ваш автомобиль может указать вам ближайшую заправку, когда у вас кончается бензин. Вы можете попробовать ввести другое имя пользователя и пароль.
Swift поддерживает обработку ошибок с помощью блока кода do-try-catch.
Выбрасывание ошибок
Когда в вашем коде возникает сценарий, который может привести к ошибке, вы можете выбросить ошибку:
if fuel < 1000 { throw RocketError.insufficientFuel }
В приведенном выше коде ключевое слово throw используется для выдачи ошибки типа RocketError.insufficientFuel, когда переменная fuel меньше, чем 1000.
Представьте, что мы пытаемся запустить ракету:
func igniteRockets(fuel: Int, astronauts: Int) throws { if fuel < 1000 { throw RocketError.insufficientFuel } else if astronauts < 3 { throw RocketError.insufficientAstronauts(needed: 3) } // Запуск ракеты print("3... 2... 1... Старт!") }
Функция igniteRockets(fuel:astronauts:) будет запускать ракеты, только если значение fuel больше или равно 1000 и если на борту есть как минимум 3 астронавта.
Функция igniteRockets(…) также помечается ключевым словом throws. Это ключевое слово указывает, что ошибки должны быть обработаны.
В приведенном выше коде мы используем тип ошибки RocketError:
enum RocketError: Error { case insufficientFuel case insufficientAstronauts(needed: Int) case unknownError }
Данное перечисление определяет три типа ошибок: .insufficientFuel, insufficientAstronauts(needed) и .unknownError. Определение ваших собственных типов ошибок полезно, потому что это поможет четко понять, что эти ошибки означают в вашем коде.
Возьмем, например, ошибку insufficientAstronauts(needed:). Когда выдается эта ошибка, вы можете использовать аргумент needed:, который указывает, сколько астронавтов необходимо для успешного запуска ракеты.
Ключевое слово throw имеет тот же эффект, что и ключевое слово return. Когда выполняется throw, выполнение функции останавливается, и выброшенная ошибка передается вызывающей функции.
Теперь мы можем использовать обработку ошибок, чтобы соответствующим образом реагировать на сценарии ошибок. Обработка ошибок в Swift осуществляется с помощью блока кода do-try-catch:
do { try igniteRockets(fuel: 5000, astronauts: 1) } catch { print(error) }
Обработка ошибок имеет три аспекта:
- К функции, которая может вызвать ошибку, добавляется ключевое слово try.
- Блок кода, который включает ключевое слово try, обернут в do { … }.
- Один или несколько блоков catch { … } могут быть присоединены к do { … } для обработки отдельных случаев ошибок.
Если функция выдает ошибку, вызывается блок catch. В данном случае это выводит ошибку на консоль.
Вы также можете реагировать на ошибки в индивидуальном порядке:
do { try igniteRockets(fuel: 5000, astronauts: 1) } catch RocketError.insufficientFuel { print("Ракете нужно больше топлива!") } catch RocketError.insufficientAstronauts(let needed) { print("Нужно как минимум (needed) астронавта...") }
Вышеуказанные блоки catch вызываются на основании отдельных перечислений RocketError. Вы можете напрямую получить доступ к связанным значениям перечислений, таких как needed. Также вы можете использовать выражения с шаблоном where чтобы получить больший контроль над ошибочным сценарием.
enum RocketError: Error { case insufficientFuel case insufficientAstronauts(needed: Int) case unknownError } func igniteRockets(fuel: Int, astronauts: Int) throws { if fuel < 1000 { throw RocketError.insufficientFuel } else if astronauts < 3 { throw RocketError.insufficientAstronauts(needed: 3) } // Ignite rockets print("3... 2... 1... Полет!") } do { try igniteRockets(fuel: 5000, astronauts: 1) } catch { print(error) }
Преобразование ошибок в опционалы с помощью try?
Целью обработки ошибок является явное определение того, что происходит при возникновении ошибки. Это позволяет нам реагировать определенным образом на ошибки.
В некоторых случаях нас не волнует сама ошибка. Нам просто нужно получить значение из функции. И если возникает ошибка, мы можем возвратить nil. Эта возможность доступна с помощью ключевого слова try? Когда вы используете try?, вам не нужно использовать полный блок кода do-try-catch.
let result = try? calculateValue(for: 42)
Представьте, что функция может выбрасывать ошибки, если ее параметр недействителен. Вместо обработки ошибки мы конвертируем возвращаемое значение в опциональное.
Возможны два сценария:
- Функция не выдает ошибку и возвращает значение, которое присваивается константе result.
- Функция выдает ошибку и не возвращает значение. Это означает, что константе result присваивается nil.
Обработка ошибок с помощью try? означает, что вы можете воспользоваться синтаксисом, специфичным для опционалов, таких как объединение по nil и опциональное связывание:
if let result = try? calculateValue(for: 99) { // } let result = try? calculateValue(for: 123) ?? 101
Отключение обработки ошибок с помощью try!
Вы можете полностью отключить обработку ошибок с помощью try!. Ключевое слово try! используется для принудиального извлечения опционального значения.
В отличие от того try?, который возвращает опциональное значение, синтаксис try! приведет к сбою вашего кода в случае возникновения ошибки. Есть два различных сценария, в которых использование try! может быть полезно:
- Используйте try!, когда вы на 100% уверенны, что ошибка не возникнет.
- Используйте, try!, когда невозможно продолжить выполнение кода.
Представьте, что вы пишите приложение, в которое встроен файл базы данных. Функция загрузки базы данных выдает ошибку, когда база данных повреждена. Вы можете использовать try! для загрузки базы данных в память, потому что, если база данных повреждена, приложение все равно не сможет быть использовано.
Error Handling in Swift 2.0
As a tentpole feature for Swift 2.0, we are introducing a new
first-class error handling model. This feature provides standardized
syntax and language affordances for throwing, propagating, catching, and
manipulating recoverable error conditions.
Error handling is a well-trod path, with many different approaches in
other languages, many of them problematic in various ways. We believe
that our approach provides an elegant solution, drawing on the lessons
we’ve learned from other languages and fixing or avoiding some of the
pitfalls. The result is expressive and concise while still feeling
explicit, safe, and familiar; and we believe it will work beautifully
with the Cocoa APIs.
We’re intentionally not using the term «exception handling», which
carries a lot of connotations from its use in other languages. Our
proposal has some similarities to the exceptions systems in those
languages, but it also has a lot of important differences.
Kinds of Error
What exactly is an «error»? There are many possible error conditions,
and they don’t all make sense to handle in exactly the same way,
because they arise in different circumstances and programmers have to
react to them differently.
We can break errors down into four categories, in increasing order of
severity:
A simple domain error arises from an operation that can fail in some
obvious way and which is often invoked speculatively. Parsing an integer
from a string is a really good example. The client doesn’t need a
detailed description of the error and will usually want to handle the
error immediately. These errors are already well-modeled by returning an
optional value; we don’t need a more complex language solution for
them.
A recoverable error arises from an operation which can fail in
complex ways, but whose errors can be reasonably anticipated in advance.
Examples including opening a file or reading from a network connection.
These are the kinds of errors that Apple’s APIs use NSError for today,
but there are close analogues in many other APIs, such as errno
in
POSIX.
Ignoring this kind of error is usually a bad idea, and it can even be
dangerous (e.g. by introducing a security hole). Developers should be
strongly encouraged to write code that handles the error. It’s common
for developers to want to handle errors from different operations in the
same basic way, either by reporting the error to the user or passing the
error back to their own clients.
These errors will be the focus of this proposal.
The final two classes of error are outside the scope of this proposal. A
universal error is theoretically recoverable, but by its nature the
language can’t help the programmer anticipate where it will come from.
A logic failure arises from a programmer mistake and should not be
recoverable at all. In our system, these kinds of errors are reported
either with Objective-C/C++ exceptions or simply by logging a message
and calling abort()
. Both kinds of error are discussed extensively in
the rationale. Having considered them carefully, we believe that we can
address them in a later release without significant harm.
Aspects of the Design
This approach proposed here is very similar to the error handling model
manually implemented in Objective-C with the NSError
convention.
Notably, the approach preserves these advantages of this convention:
- Whether a method produces an error (or not) is an explicit part of
its API contract. - Methods default to not producing errors unless they are explicitly
marked. - The control flow within a function is still mostly explicit: a
maintainer can tell exactly which statements can produce an error,
and a simple inspection reveals how the function reacts to the
error. - Throwing an error provides similar performance to allocating an
error and returning it — it isn’t an expensive, table-based stack
unwinding process. - Cocoa APIs using standard
NSError
patterns can be imported into
this world automatically. Other common patterns (e.g.CFError
,
errno
) can be added to the model in future versions of Swift.
In addition, we feel that this design improves on Objective-C’s error
handling approach in a number of ways:
- It eliminates a lot of boilerplate control-flow code for propagating
errors. - The syntax for error handling will feel familiar to people used to
exception handling in other languages. - Defining custom error types is simple and ties in elegantly with
Swift enums.
As to basic syntax, we decided to stick with the familiar language of
exception handling. We considered intentionally using different terms
(like raise
/ handle
) to try to distinguish our approach from other
languages. However, by and large, error propagation in this proposal
works like it does in exception handling, and people are inevitably
going to make the connection. Given that, we couldn’t find a compelling
reason to deviate from the throw
/ catch
legacy.
This document just contains the basic proposal and will be very light on
rationale. We considered many different languages and programming
environments as part of making this proposal, and there’s an extensive
discussion of them in the separate rationale document. For example, that
document explains why we don’t simply allow all functions to throw, why
we don’t propagate errors using simply an ErrorOr<T>
return type, and
why we don’t just make error propagation part of a general monad
feature. We encourage you to read that rationale if you’re interested
in understanding why we made the decisions we did.
With that out of the way, let’s get to the details of the proposal.
Typed propagation
Whether a function can throw is part of its type. This applies to all
functions, whether they’re global functions, methods, or closures.
By default, a function cannot throw. The compiler statically enforces
this: anything the function does which can throw must appear in a
context which handles all errors.
A function can be declared to throw by writing throws
on the function
declaration or type:
func foo() -> Int { // This function is not permitted to throw. func bar() throws -> Int { // This function is permitted to throw.
throws
is written before the arrow to give a sensible and consistent
grammar for function types and implicit ()
result types, e.g.:
func baz() throws { // Takes a 'callback' function that can throw. // 'fred' itself can also throw. func fred(_ callback: (UInt8) throws -> ()) throws { // These are distinct types. let a : () -> () -> () let b : () throws -> () -> () let c : () -> () throws -> () let d : () throws -> () throws -> ()
For curried functions, throws
only applies to the innermost function.
This function has type (Int) -> (Int) throws -> Int
:
func jerry(_ i: Int)(j: Int) throws -> Int {
throws
is tracked as part of the type system: a function value must
also declare whether it can throw. Functions that cannot throw are a
subtype of functions that can, so you can use a function that can’t
throw anywhere you could use a function that can:
func rachel() -> Int { return 12 } func donna(_ generator: () throws -> Int) -> Int { ... } donna(rachel)
The reverse is not true, since the caller would not be prepared to
handle the error.
A call to a function which can throw within a context that is not
allowed to throw is rejected by the compiler.
It isn’t possible to overload functions solely based on whether the
functions throw. That is, this is not legal:
func foo() { func foo() throws {
A throwing method cannot override a non-throwing method or satisfy a
non-throwing protocol requirement. However, a non-throwing method can
override a throwing method or satisfy a throwing protocol requirement.
It is valuable to be able to overload higher-order functions based on
whether an argument function throws, so this is allowed:
func foo(_ callback: () throws -> Bool) { func foo(_ callback: () -> Bool) {
rethrows
Functions which take a throwing function argument (including as an
autoclosure) can be marked as rethrows
:
extension Array { func map<U>(_ fn: ElementType throws -> U) rethrows -> [U] }
It is an error if a function declared rethrows
does not include a
throwing function in at least one of its parameter clauses.
rethrows
is identical to throws
, except that the function promises
to only throw if one of its argument functions throws.
More formally, a function is rethrowing-only for a function f if:
- it is a throwing function parameter of f,
- it is a non-throwing function, or
- it is implemented within f (i.e. it is either f or a function or
closure defined therein) and it does not throw except by either:- calling a function that is rethrowing-only for f or
- calling a function that is
rethrows
, passing only functions
that are rethrowing-only for f.
It is an error if a rethrows
function is not rethrowing-only for
itself.
A rethrows
function is considered to be a throwing function. However,
a direct call to a rethrows
function is considered to not throw if it
is fully applied and none of the function arguments can throw. For
example:
// This call to map is considered not to throw because its // argument function does not throw. let absolutePaths = paths.map { "/" + $0 } // This call to map is considered to throw because its // argument function does throw. let streams = try absolutePaths.map { try InputStream(filename: $0) }
For now, rethrows
is a property of declared functions, not of function
values. Binding a variable (even a constant) to a function loses the
information that the function was rethrows
, and calls to it will use
the normal rules, meaning that they will be considered to throw
regardless of whether a non-throwing function is passed.
For the purposes of override and conformance checking, rethrows
lies
between throws
and non-throws
. That is, an ordinary throwing method
cannot override a rethrows
method, which cannot override a
non-throwing method; but an ordinary throwing method can be overridden
by a rethrows
method, which can be overridden by a non-throwing
method. Equivalent rules apply for protocol conformance.
Throwing an error
The throw
statement begins the propagation of an error. It always
takes an argument, which can be any value that conforms to the Error
protocol (described below).
if timeElapsed > timeThreshold { throw HomeworkError.Overworked } throw NSError(domain: "whatever", code: 42, userInfo: nil)
As mentioned above, attempting to throw an error out of a function not
marked throws
is a static compiler error.
Catching errors
A catch
clause includes an optional pattern that matches the error.
This pattern can use any of the standard pattern-matching tools provided
by switch
statements in Swift, including boolean where
conditions.
The pattern can be omitted; if so, a where
condition is still
permitted. If the pattern is omitted, or if it does not bind a different
name to the error, the name error
is automatically bound to the error
as if with a let
pattern.
The try
keyword is used for other purposes which it seems to fit far
better (see below), so catch
clauses are instead attached to a
generalized do
statement:
// Simple do statement (without a trailing while condition), // just provides a scope for variables defined inside of it. do { let x = foo() } // do statement with two catch clauses. do { ... } catch HomeworkError.Overworked { // a conditionally-executed catch clause } catch _ { // a catch-all clause. }
As with switch
statements, Swift makes an effort to understand whether
catch clauses are exhaustive. If it can determine it is, then the
compiler considers the error to be handled. If not, the error
automatically propagates out of scope, either to a lexically enclosing
catch
clause or out of the containing function (which must be marked
throws
).
We expect to refine the catch
syntax with usage experience.
Error
The Swift standard library will provide Error
, a protocol with a very
small interface (which is not described in this proposal). The standard
pattern should be to define the conformance of an enum
to the type:
enum HomeworkError : Error { case Overworked case Impossible case EatenByCat(Cat) case StopStressingMeWithYourRules }
The enum
provides a namespace of errors, a list of possible errors
within that namespace, and optional values to attach to each option.
Note that this corresponds very cleanly to the NSError
model of an
error domain, an error code, and optional user data. We expect to import
system error domains as enums that follow this approach and implement
Error
. NSError
and CFError
themselves will also conform to
Error
.
The physical representation (still being nailed down) will make it
efficient to embed an NSError
as an Error
and vice-versa. It should
be possible to turn an arbitrary Swift enum
that conforms to Error
into an NSError
by using the qualified type name as the domain key,
the enumerator as the error code, and turning the payload into user
data.
Automatic, marked, propagation of errors
Once an error is thrown, Swift will automatically propagate it out of
scopes (that permit it), rather than relying on the programmer to
manually check for errors and do their own control flow. This is just a
lot less boilerplate for common error handling tasks. However, doing
this naively would introduce a lot of implicit control flow, which makes
it difficult to reason about the function’s behavior. This is a serious
maintenance problem and has traditionally been a considerable source of
bugs in languages that heavily use exceptions.
Therefore, while Swift automatically propagates errors, it requires that
statements and expressions that can implicitly throw be marked with the
try
keyword. For example:
func readStuff() throws { // loadFile can throw an error. If so, it propagates out of readStuff. try loadFile("mystuff.txt") // This is a semantic error; the 'try' keyword is required // to indicate that it can throw. var y = stream.readFloat() // This is okay; the try covers the entire statement. try y += stream.readFloat() // This try applies to readBool(). if try stream.readBool() { // This try applies to both of these calls. let x = try stream.readInt() + stream.readInt() } if let err = stream.getOutOfBandError() { // Of course, the programmer doesn't have to mark explicit throws. throw err } }
Developers can choose to «scope» the try
very tightly by writing it
within parentheses or on a specific argument or list element:
// Ok. let x = (try stream.readInt()) + (try stream.readInt()) // Semantic error: the try only covers the parenthesized expression. let x2 = (try stream.readInt()) + stream.readInt() // The try applies to the first array element. Of course, the // developer could cover the entire array by writing the try outside. let array = [ try foo(), bar(), baz() ]
Some developers may wish to do this to make the specific throwing calls
very clear. Other developers may be content with knowing that something
within a statement can throw. The compiler’s fixit hints will guide
developers towards inserting a single try
that covers the entire
statement. This could potentially be controlled someday by a coding
style flag passed to the compiler.
try!
To concisely indicate that a call is known to not actually throw at
runtime, try
can be decorated with !
, turning the error check into a
runtime assertion that the call does not throw.
For the purposes of checking that all errors are handled, a try!
expression is considered to handle any error originating from within its
operand.
try!
is otherwise exactly like try
: it can appear in exactly the
same positions and doesn’t affect the type of an expression.
Manual propagation and manipulation of errors
Taking control over the propagation of errors is important for some
advanced use cases (e.g. transporting an error result across threads
when synchronizing a future) and can be more convenient or natural for
specific use cases (e.g. handling a specific call differently within a
context that otherwise allows propagation).
As such, the Swift standard library should provide a standard Rust-like
Result<T>
enum, along with API for working with it, e.g.:
- A function to evaluate an error-producing closure and capture the
result as aResult<T>
. - A function to unpack a
Result<T>
by either returning its value or
propagating the error in the current context.
This is something that composes on top of the basic model, but that has
not been designed yet and details aren’t included in this proposal.
The name Result<T>
is a stand-in and needs to be designed and
reviewed, as well as the basic operations on the type.
defer
Swift should provide a defer
statement that sets up an ad hoc
clean-up action to be run when the current scope is exited. This
replicates the functionality of a Java-style finally
, but more cleanly
and with less nesting.
This is an important tool for ensuring that explicitly-managed resources
are released on all paths. Examples include closing a network connection
and freeing memory that was manually allocated. It is convenient for all
kinds of error-handling, even manual propagation and simple domain
errors, but is especially nice with automatic propagation. It is also a
crucial part of our long-term vision for universal errors.
defer
may be followed by an arbitrary statement. The compiler should
reject a defer
action that might terminate early, whether by throwing
or with return
, break
, or continue
.
Example:
if exists(filename) { let file = open(filename, O_READ) defer close(file) while let line = try file.readline() { ... } // close occurs here, at the end of the formal scope. }
If there are multiple defer statements in a scope, they are guaranteed
to be executed in reverse order of appearance. That is:
let file1 = open("hello.txt") defer close(file1) let file2 = open("world.txt") defer close(file2) ... // file2 will be closed first.
A potential extension is to provide a convenient way to mark that a
defer action should only be taken if an error is thrown. This is a
convenient shorthand for controlling the action with a flag. We will
evaluate whether adding complexity to handle this case is justified
based on real-world usage experience.
Importing Cocoa
If possible, Swift’s error-handling model should transparently work
with the SDK with a minimal amount of effort from framework owners.
We believe that we can cover the vast majority of Objective-C APIs with
NSError**
out-parameters by importing them as throws
and removing
the error clause from their signature. That is, a method like this one
from NSAttributedString
:
- (NSData *)dataFromRange:(NSRange)range documentAttributes:(NSDictionary *)dict error:(NSError **)error;
would be imported as:
func dataFromRange( _ range: NSRange, documentAttributes dict: NSDictionary ) throws -> NSData
There are a number of cases to consider, but we expect that most can be
automatically imported without extra annotation in the SDK, by using a
couple of simple heuristics:
-
The most common pattern is a
BOOL
result, where a false value
means an error occurred. This seems unambiguous. -
Also common is a pointer result, where a
nil
result usually means
an error occurred. This appears to be universal in Objective-C; APIs
that can returnnil
results seem to do so via out-parameters. So
it seems to be safe to make a policy decision that it’s okay to
assume that anil
result is an error by default.If the pattern for a method is that a
nil
result means it produced
an error, then the result can be imported as a non-optional type. -
A few APIs return
void
. As far as I can tell, for all of these,
the caller is expected to check for a non-nil
error.
For other sentinel cases, we can consider adding a new clang attribute
to indicate to the compiler what the sentinel is:
- There are several APIs returning
NSInteger
orNSUInteger
. At
least some of these return 0 on error, but that doesn’t seem like a
reasonable general assumption. AVFoundation
provides a couple methods returning
AVKeyValueStatus
. These produce an error if the API returned
AVKeyValueStatusFailed
, which, interestingly enough, is not the
zero value.
The clang attribute would specify how to test the return value for an
error. For example:
+ (NSInteger)writePropertyList:(id)plist toStream:(NSOutputStream *)stream format:(NSPropertyListFormat)format options:(NSPropertyListWriteOptions)opt error:(out NSError **)error NS_ERROR_RESULT(0); - (AVKeyValueStatus)statusOfValueForKey:(NSString *)key error:(NSError **) NS_ERROR_RESULT(AVKeyValueStatusFailed);
We should also provide a Clang attribute which specifies that the
correct way to test for an error is to check the out-parameter. Both of
these attributes could potentially be used by the static analyzer, not
just Swift. (For example, they could try to detect an invalid error
check.)
Cases that do not match the automatically imported patterns and that
lack an attribute would be left unmodified (i.e., they’d keep their
NSErrorPointer argument) and considered «not awesome» in the SDK
auditing tool. These will still be usable in Swift: callers will get the
NSError back like they do today, and have to throw the result manually.
For initializers, importing an initializer as throwing takes precedence
over importing it as failable. That is, an imported initializer with a
nullable result and an error parameter would be imported as throwing.
Throwing initializers have very similar constraints to failable
initializers; in a way, it’s just a new axis of failability.
One limitation of this approach is that we need to be able to
reconstruct the selector to use when an overload of a method is
introduced. For this reason, the import is likely to be limited to
methods where the error parameter is the last one and the corresponding
selector chunk is either error:
or the first chunk (see below).
Empirically, this seems to do the right thing for all but two sets of
APIs in the public API:
-
The
ISyncSessionDriverDelegate
category onNSObject
declares
half-a-dozen methods like this:- (BOOL)sessionDriver:(ISyncSessionDriver *)sender didRegisterClientAndReturnError:(NSError **)outError;
Fortunately, these delegate methods were all deprecated in Lion, and
are thus unavailable in Swift. -
NSFileCoordinator
has half a dozen methods where theerror:
clause is second-to-last, followed by a block argument. These
methods are not deprecated as far as I know.
The above translation rule would import methods like this one from
NSDocument
:
- (NSDocument *)duplicateAndReturnError:(NSError **)outError;
like so:
func duplicateAndReturnError() throws -> NSDocument
The AndReturnError
bit is common but far from universal; consider this
method from NSManagedObject
:
- (BOOL)validateForDelete:(NSError **)error;
This would be imported as:
func validateForDelete() throws
This is a really nice import, and it’s somewhat unfortunate that we
can’t import duplicateAndReturnError:
as duplicate()
.
Potential future extensions to this model
We believe that the proposal above is sufficient to provide a huge step
forward in error handling in Swift programs, but there is always more to
consider in the future. Some specific things we’ve discussed (and may
come back to in the future) but don’t consider to be core to the Swift
2.0 model are:
Higher-order polymorphism
We should make it easy to write higher-order functions that behave
polymorphically with respect to whether their arguments throw. This can
be done in a fairly simple way: a function can declare that it throws if
any of a set of named arguments do. As an example (using strawman
syntax):
func map<T, U>(_ array: [T], fn: T -> U) throwsIf(fn) -> [U] { ... }
There’s no need for a more complex logical operator than disjunction
for normal higher-order stuff.
This feature is highly desired (e.g. it would allow many otherwise
redundant overloads to be collapsed into a single definition), but it
may or may not make it into Swift 2.0 based on schedule limitations.
Generic polymorphism
For similar reasons to higher-order polymorphism, we should consider
making it easier to parameterize protocols on whether their operations
can throw. This would allow the writing of generic algorithms, e.g. over
Sequence
, that handle both conformances that cannot throw (like
Array
) and those that can (like a hypothetical cloud-backed
implementation).
However, this would be a very complex feature, yet to be designed, and
it is far out-of-scope for Swift 2.0. In the meantime, most standard
protocols will be written to not allow throwing conformances, so as to
not burden the use of common generic algorithms with spurious
error-handling code.
Statement-like functions
Some functions are designed to take trailing closures that feel like
sub-statements. For example, autoreleasepool
can be used this way:
autoreleasepool { foo() }
The error-handling model doesn’t cause major problems for this. The
compiler can infer that the closure throws, and autoreleasepool
can be
overloaded on whether its argument closure throws; the overload that
takes a throwing closures would itself throw.
There is one minor usability problem here, though. If the closure
contains throwing expressions, those expressions must be explicitly
marked within the closure with try
. However, from the compiler’s
perspective, the call to autoreleasepool
is also a call that can
throw, and so it must also be marked with try
:
try autoreleasepool { // 'try' is required here... let string = try parseString() // ...and here. ... }
This marking feels redundant. We want functions like autoreleasepool
to feel like statements, but marks inside built-in statements like if
don’t require the outer statement to be marked. It would be better if
the compiler didn’t require the outer try
.
On the other hand, the «statement-like» story already has a number of
other holes: for example, break
, continue
, and return
behave
differently in the argument closure than in statements. In the future,
we may consider fixing that; that fix will also need to address the
error-propagation problem.
using
A using
statement would acquire a resource, holds it for a fixed
period of time, optionally binds it to a name, and then releases it
whenever the controlled statement exits. using
has many similarities
to defer
. It does not subsume defer
, which is useful for many ad-hoc
and tokenless clean-ups. But it could be convenient for the common
pattern of a type-directed clean-up.
Automatically importing CoreFoundation and C functions
CF APIs use CFErrorRef
pretty reliably, but there are several problems
here: 1) the memory management rules for CFErrors are unclear and
potentially inconsistent. 2) we need to know when an error is raised.
In principle, we could import POSIX functions into Swift as throwing
functions, filling in the error from errno
. It’s nearly impossible to
imagine doing this with an automatic import rule, however; much more
likely, we’d need to wrap them all in an overlay.
In both cases, it is possible to pull these into the Swift error
handling model, but because this is likely to require massive SDK
annotations it is considered out of scope for iOS 9/OS X 10.11 & Swift
2.0.
Unexpected and universal errors
As discussed above, we believe that we can extend our current model to
support untyped propagation for universal errors. Doing this well, and
in particular doing it without completely sacrificing code size and
performance, will take a significant amount of planning and insight. For
this reason, it is considered well out of scope for Swift 2.0.
Мы используем обработку ошибок с помощью do-try-catch для реагирования на исправимые ошибки. Это дает нам больший контроль над различными ошибочными сценариями, которые могут возникнуть в нашем коде, например, при вводе неправильного имени пользователя или пароля.
Зачем нужно отслеживать ошибки?
В приложении некоторые ошибки могут быть результатом ошибок программиста. Когда ваше приложение вылетает с сообщением «Index out of bounds», вы, вероятно, где-то допустили ошибку. И точно так же, когда вы принудительно извлекаете опциональное значение, которое имеет значение nil, ваше приложение падает.
В практической разработке iOS некоторые ошибки являются частью работы приложения, например, сообщение «Недостаточно средств» при попытке оплаты с помощью карты.
Ошибки такого рода исправимы. Их можно обработать и отреагировать соответствующим образом. К примеру:
- При попытке снять деньги в банкомате отображается «Неверный PIN-код».
- Ваш автомобиль показывает индикатор низкого уровня топлива при попытке запустить двигатель.
- Попытка аутентификации для API возвращает «Неверное имя пользователя / пароль».
Вы можете работать с этими ошибками, отобразив сообщение с предупреждением или сделав что-то еще. Например, ваша карта блокируется после 3 неудачных попыток. Ваш автомобиль может указать вам ближайшую заправку, когда у вас кончается бензин. Вы можете попробовать ввести другое имя пользователя и пароль.
Swift поддерживает обработку ошибок с помощью блока кода do-try-catch.
Выбрасывание ошибок
Когда в вашем коде возникает сценарий, который может привести к ошибке, вы можете выбросить ошибку:
if fuel < 1000 { throw RocketError.insufficientFuel }
В приведенном выше коде ключевое слово throw используется для выдачи ошибки типа RocketError.insufficientFuel, когда переменная fuel меньше, чем 1000.
Представьте, что мы пытаемся запустить ракету:
func igniteRockets(fuel: Int, astronauts: Int) throws { if fuel < 1000 { throw RocketError.insufficientFuel } else if astronauts < 3 { throw RocketError.insufficientAstronauts(needed: 3) } // Запуск ракеты print("3... 2... 1... Старт!") }
Функция igniteRockets(fuel:astronauts:) будет запускать ракеты, только если значение fuel больше или равно 1000 и если на борту есть как минимум 3 астронавта.
Функция igniteRockets(…) также помечается ключевым словом throws. Это ключевое слово указывает, что ошибки должны быть обработаны.
В приведенном выше коде мы используем тип ошибки RocketError:
enum RocketError: Error { case insufficientFuel case insufficientAstronauts(needed: Int) case unknownError }
Данное перечисление определяет три типа ошибок: .insufficientFuel, insufficientAstronauts(needed) и .unknownError. Определение ваших собственных типов ошибок полезно, потому что это поможет четко понять, что эти ошибки означают в вашем коде.
Возьмем, например, ошибку insufficientAstronauts(needed:). Когда выдается эта ошибка, вы можете использовать аргумент needed:, который указывает, сколько астронавтов необходимо для успешного запуска ракеты.
Ключевое слово throw имеет тот же эффект, что и ключевое слово return. Когда выполняется throw, выполнение функции останавливается, и выброшенная ошибка передается вызывающей функции.
Теперь мы можем использовать обработку ошибок, чтобы соответствующим образом реагировать на сценарии ошибок. Обработка ошибок в Swift осуществляется с помощью блока кода do-try-catch:
do { try igniteRockets(fuel: 5000, astronauts: 1) } catch { print(error) }
Обработка ошибок имеет три аспекта:
- К функции, которая может вызвать ошибку, добавляется ключевое слово try.
- Блок кода, который включает ключевое слово try, обернут в do { … }.
- Один или несколько блоков catch { … } могут быть присоединены к do { … } для обработки отдельных случаев ошибок.
Если функция выдает ошибку, вызывается блок catch. В данном случае это выводит ошибку на консоль.
Вы также можете реагировать на ошибки в индивидуальном порядке:
do { try igniteRockets(fuel: 5000, astronauts: 1) } catch RocketError.insufficientFuel { print("Ракете нужно больше топлива!") } catch RocketError.insufficientAstronauts(let needed) { print("Нужно как минимум (needed) астронавта...") }
Вышеуказанные блоки catch вызываются на основании отдельных перечислений RocketError. Вы можете напрямую получить доступ к связанным значениям перечислений, таких как needed. Также вы можете использовать выражения с шаблоном where чтобы получить больший контроль над ошибочным сценарием.
enum RocketError: Error { case insufficientFuel case insufficientAstronauts(needed: Int) case unknownError } func igniteRockets(fuel: Int, astronauts: Int) throws { if fuel < 1000 { throw RocketError.insufficientFuel } else if astronauts < 3 { throw RocketError.insufficientAstronauts(needed: 3) } // Ignite rockets print("3... 2... 1... Полет!") } do { try igniteRockets(fuel: 5000, astronauts: 1) } catch { print(error) }
Преобразование ошибок в опционалы с помощью try?
Целью обработки ошибок является явное определение того, что происходит при возникновении ошибки. Это позволяет нам реагировать определенным образом на ошибки.
В некоторых случаях нас не волнует сама ошибка. Нам просто нужно получить значение из функции. И если возникает ошибка, мы можем возвратить nil. Эта возможность доступна с помощью ключевого слова try? Когда вы используете try?, вам не нужно использовать полный блок кода do-try-catch.
let result = try? calculateValue(for: 42)
Представьте, что функция может выбрасывать ошибки, если ее параметр недействителен. Вместо обработки ошибки мы конвертируем возвращаемое значение в опциональное.
Возможны два сценария:
- Функция не выдает ошибку и возвращает значение, которое присваивается константе result.
- Функция выдает ошибку и не возвращает значение. Это означает, что константе result присваивается nil.
Обработка ошибок с помощью try? означает, что вы можете воспользоваться синтаксисом, специфичным для опционалов, таких как объединение по nil и опциональное связывание:
if let result = try? calculateValue(for: 99) { // } let result = try? calculateValue(for: 123) ?? 101
Отключение обработки ошибок с помощью try!
Вы можете полностью отключить обработку ошибок с помощью try!. Ключевое слово try! используется для принудиального извлечения опционального значения.
В отличие от того try?, который возвращает опциональное значение, синтаксис try! приведет к сбою вашего кода в случае возникновения ошибки. Есть два различных сценария, в которых использование try! может быть полезно:
- Используйте try!, когда вы на 100% уверенны, что ошибка не возникнет.
- Используйте, try!, когда невозможно продолжить выполнение кода.
Представьте, что вы пишите приложение, в которое встроен файл базы данных. Функция загрузки базы данных выдает ошибку, когда база данных повреждена. Вы можете использовать try! для загрузки базы данных в память, потому что, если база данных повреждена, приложение все равно не сможет быть использовано.
Время на прочтение
5 мин
Количество просмотров 10K
Сегодня мы приготовили перевод для тех, кто так же, как автор статьи, при изучении Документации языка программирования Swift избегает главы «Error Handling».
Из статьи вы узнаете:
- что такое оператор if-else и что с ним не так;
- как подружиться с Error Handling;
- когда стоит использовать Try! и Try?
Моя история
Когда я был младше, я начинал изучать документацию языка Swift. Я по несколько раз прочёл все главы, кроме одной: «Error Handling». Отчего-то мне казалось, что нужно быть профессиональным программистом, чтобы понять эту главу.
Я боялся обработки ошибок. Такие слова, как catch, try, throw и throws, казались бессмысленными. Они просто пугали. Неужели они не выглядят устрашающими для человека, который видит их в первый раз? Но не волнуйтесь, друзья мои. Я здесь, чтобы помочь вам.
Как я объяснил своей тринадцатилетней сестре, обработка ошибок – это всего лишь ещё один способ написать блок if-else для отправки сообщения об ошибке.
Сообщение об ошибке от Tesla Motors
Как вы наверняка знаете, у автомобилей Tesla есть функция автопилота. Но, если в работе машины по какой-либо причине происходит сбой, она просит вас взять руль в руки и сообщает об ошибке. В этом уроке мы узнаем, как выводить такое сообщение с помощью Error Handling.
Мы создадим программу, которая будет распознавать такие объекты, как светофоры на улицах. Для этого нужно знать как минимум машинное обучение, векторное исчисление, линейную алгебру, теорию вероятности и дискретную математику. Шутка.
Знакомство с оператором if-else
Чтобы максимально оценить Error Handling в Swift, давайте оглянемся в прошлое. Вот что многие, если не все, начинающие разработчики сделали бы, столкнувшись с сообщением об ошибке:
var isInControl = true
func selfDrive() {
if isInControl {
print("You good, let me ride this car for ya")
} else {
print("Hold the handlebar RIGHT NOW, or you gone die")
}
}
selfDrive() // "You good..."
Проблема
Самая большая проблема заключается в удобочитаемости кода, когда блок else становится слишком громоздким. Во-первых, вы не поймёте, содержит ли сама функция сообщение об ошибке, до тех пор, пока не прочитаете функцию от начала до конца или если не назовёте ее, например, selfDriveCanCauseError, что тоже сработает.
Смотрите, функция может убить водителя. Необходимо в недвусмысленных выражениях предупредить свою команду о том, что эта функция опасна и даже может быть смертельной, если невнимательно с ней обращаться.
С другой проблемой можно столкнуться при выполнении некоторых сложных функций или действий внутри блока else. Например:
else {
print("Hold the handle bar Right now...")
// If handle not held within 5 seconds, car will shut down
// Slow down the car
// More code ...
// More code ...
}
Блок else раздувается, и работать с ним – все равно что пытаться играть в баскетбол в зимней одежде (по правде говоря, я так и делаю, так как в Корее достаточно холодно). Вы понимаете, о чём я? Это некрасиво и нечитабельно.
Поэтому вы просто могли бы добавить функцию в блок else вместо прямых вызовов.
else {
slowDownTheCar()
shutDownTheEngine()
}
Однако при этом сохраняется первая из выделенных мной проблем, плюс нет какого-то определённого способа обозначить, что функция selfDrive() опасна и что с ней нужно обращаться с осторожностью. Поэтому предлагаю погрузиться в Error Handling, чтобы писать модульные и точные сообщения об ошибках.
Знакомство с Error Handling
К настоящему времени вы уже знаете о проблеме If-else с сообщениями об ошибках. Пример выше был слишком простым. Давайте предположим, что есть два сообщения об ошибке:
- вы заблудились
- аккумулятор автомобиля разряжается.
Я собираюсь создать enum, который соответствует протоколу Error.
enum TeslaError: Error {
case lostGPS
case lowBattery
}
Честно говоря, я точно не знаю, что делает Error протокол, но при обработке ошибок без этого не обойдешься. Это как: «Почему ноутбук включается, когда нажимаешь на кнопку? Почему экран телефона можно разблокировать, проведя по нему пальцем?»
Разработчики Swift так решили, и я не хочу задаваться вопросом об их мотивах. Я просто использую то, что они для нас сделали. Конечно, если вы хотите разобраться подробнее, вы можете загрузить программный код Swift и проанализировать его самостоятельно – то есть, по нашей аналогии, разобрать ноутбук или iPhone. Я же просто пропущу этот шаг.
Если вы запутались, потерпите еще несколько абзацев. Вы увидите, как все станет ясно, когда TeslaError превратится в функцию.
Давайте сперва отправим сообщение об ошибке без использования Error Handling.
var lostGPS: Bool = true
var lowBattery: Bool = false
func autoDriveTesla() {
if lostGPS {
print("I'm lost, bruh. Hold me tight")
// A lot more code
}
if lowBattery {
print("HURRY! ")
// Loads of code
}
}
Итак, если бы я запустил это:
autoDriveTesla() // "HURRY! "
Но давайте используем Error Handling. В первую очередь вы должны явно указать, что функция опасна и может выдавать ошибки. Мы добавим к функции ключевое слово throws.
func autoDriveTesla() throws { ... }
Теперь функция автоматически говорит вашим товарищам по команде, что autoDriveTesla – особый случай, и им не нужно читать весь блок.
Звучит неплохо? Отлично, теперь пришло время выдавать эти ошибки, когда водитель сталкивается с lostGPA или lowBattery внутри блока Else-If. Помните про enum TeslaError?
func autoDriveTesla() throws {
if lostGPS {
throw TeslaError.lostGPS
}
if lowBattery {
throw TeslaError.lowBattery
}
Я вас всех поймаю
Если lostGPS равно true, то функция отправит TeslaError.lostGPS. Но что делать потом? Куда мы будем вставлять это сообщение об ошибке и добавлять код для блока else?
print("Bruh, I'm lost. Hold me tight")
Окей, я не хочу заваливать вас информацией, поэтому давайте начнём с того, как выполнить функцию, когда в ней есть ключевое слово throws.
Так как это особый случай, вам необходимо добавлять try внутрь блока do при работе с этой функцией. Вы такие: «Что?». Просто последите за ходом моих мыслей ещё чуть-чуть.
do {
try autoDriveTesla()
}
Я знаю, что вы сейчас думаете: «Я очень хочу вывести на экран моё сообщение об ошибке, иначе водитель умрёт».
Итак, куда мы вставим это сообщение об ошибке? Мы знаем, что функция способна отправлять 2 возможных сообщения об ошибке:
- TeslaError.lowBattery
- TeslaError.lostGPS.
Когда функция выдаёт ошибку, вам необходимо её “поймать” и, как только вы это сделаете, вывести на экран соответствующее сообщение. Звучит немного запутанно, поэтому давайте посмотрим.
var lostGPS: Bool = false
var lowBattery: Bool = true
do {
try autoDriveTesla()
} catch TeslaError.lostGPS {
print("Bruh, I'm lost. Hold me tight")
} catch TeslaError.lowBattery {
print("HURRY! ")
}
}
// Results: "HURRY! "
Теперь всё должно стать понятно. Если понятно не всё, вы всегда можете посмотреть моё видео на YouTube.
Обработка ошибок с Init
Обработка ошибок может применяться не только к функциям, но и тогда, когда вам нужно инициализировать объект. Допустим, если вы не задали имя курса, то нужно выдавать ошибку.
Если вы введёте tryUdemyCourse(name: «»), появится сообщение об ошибке.
Когда использовать Try! и Try?
Хорошо. Try используется только тогда, когда вы выполняете функцию/инициализацию внутри блока do-catch. Однако если у вас нет цели предупредить пользователя о том, что происходит, выводя сообщение об ошибке на экран, или как-то исправить ее, вам не нужен блок catch.
try?– что это?
Давайте начнём с try? Хотя это не рекомендуется,
let newCourse = try? UdemyCourse("Functional Programming")
try? всегда возвращает опциональный объект, поэтому необходимо извлечь newCourse
if let newCourse = newCourse { ... }
Если метод init выбрасывает ошибку, как, например
let myCourse = try? UdemyCourse("") // throw NameError.noName
то myCourse будет равен nil.
try! – что это?
В отличие от try? оно возвращает не опциональное значение, а обычное. Например,
let bobCourse = try! UdemyCourse("Practical POP")
bobCourse не опционально. Однако, если при методе инициализации выдается ошибка вроде,
let noCourseName = try! UdemyCourse("") // throw NameError.noName
то приложение упадёт. Так же как и в случае с принудительным извлечением с помощью !, никогда не используйте его, если вы не уверены на 101% в том, что происходит.
Ну вот и всё. Теперь вы вместе со мной поняли концепцию Error Handling. Легко и просто! И не нужно становиться профессиональным программистом.
title | description | ms.custom | ms.date | ms.prod | ms.reviewer | ms.suite | ms.tgt_pltfrm | ms.topic | ms.assetid | caps.latest.revision | author | ms.author | manager |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
SWIFT error codes in BizTalk Server | Microsoft Docs |
View the class and validation types for the SWIFT Accelerator in BizTalk Server |
08/16/2017 |
biztalk-server |
article |
03699986-965b-4a28-ab2e-09f110fb4db6 |
4 |
MandiOhlinger |
mandia |
anneta |
SWIFT defines many network-imposed validations against the set of financial (FIN) messages. Each validation relates to a type of check against the contents of the message, and is associated with a three-character error code. The first character of the error code implies the class of the problem detected, and is a letter. The remaining two characters denote the detail of the error (when combined with the class) and always appear as a two-digit code.
Class of errors
The following table lists the letter designations, validation type, rule change associated with each class of error, and whether or not the class of error is supported.
Class | Validation type and rule change | Supported? |
---|---|---|
C, D, E | Semantic validation rules 0-299 | Supported |
Knn | Invalid code word in field nn | Supported |
M50 | Message length exceeded | Unsupported |
M60 | Non-SWIFT character encountered | Supported |
T | Text validation error codes | Supported |
G | Specific error codes for message user group (MUG) Textval rules | Unsupported |
B | Special error codes for value-added services | Unsupported |
All SWIFT errors should be referenced in the SWIFT User Handbook. For more information and for a complete list of SWIFT error codes, refer to the Message Format Validation Rules volume of the SWIFT User Handbook. [!INCLUDEbtaA4SWIFT2.3abbrevnonumber] implements the rules in the September 2003 edition of this publication. You can access the SWIFT Web site at https://go.microsoft.com/fwlink/?LinkId=27885.
Validation errors
There are some codes which are defined by A4SWIFT. These error codes are used in the validation/network rules created and implemented by A4SWIFT, so there is no corresponding error code defined by SWIFT for such rules. Below table shows the error code and corresponding case in which the error is thrown. is the particular field which throws the error.
Error Code | Description |
---|---|
A4SWIFT001 | The first character of multiline field cannot be ‘:’ or ‘-‘ character for second and subsequent lines. |
A4SWIFT002 | Field contains invalid value. |
[!NOTE]
[!INCLUDEA4SWIFT_CurrentVersion_FirstRef] includes support for some legacy messages, because internal applications might use these messages. Therefore, A4SWIFT maintains the associated SWIFT rules and error codes.
More good info
Troubleshooting: Issues and Resolutions
Known Issues
Common terms and definitions
title | description | ms.custom | ms.date | ms.prod | ms.reviewer | ms.suite | ms.tgt_pltfrm | ms.topic | ms.assetid | caps.latest.revision | author | ms.author | manager |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
SWIFT error codes in BizTalk Server | Microsoft Docs |
View the class and validation types for the SWIFT Accelerator in BizTalk Server |
08/16/2017 |
biztalk-server |
article |
03699986-965b-4a28-ab2e-09f110fb4db6 |
4 |
MandiOhlinger |
mandia |
anneta |
SWIFT defines many network-imposed validations against the set of financial (FIN) messages. Each validation relates to a type of check against the contents of the message, and is associated with a three-character error code. The first character of the error code implies the class of the problem detected, and is a letter. The remaining two characters denote the detail of the error (when combined with the class) and always appear as a two-digit code.
Class of errors
The following table lists the letter designations, validation type, rule change associated with each class of error, and whether or not the class of error is supported.
Class | Validation type and rule change | Supported? |
---|---|---|
C, D, E | Semantic validation rules 0-299 | Supported |
Knn | Invalid code word in field nn | Supported |
M50 | Message length exceeded | Unsupported |
M60 | Non-SWIFT character encountered | Supported |
T | Text validation error codes | Supported |
G | Specific error codes for message user group (MUG) Textval rules | Unsupported |
B | Special error codes for value-added services | Unsupported |
All SWIFT errors should be referenced in the SWIFT User Handbook. For more information and for a complete list of SWIFT error codes, refer to the Message Format Validation Rules volume of the SWIFT User Handbook. [!INCLUDEbtaA4SWIFT2.3abbrevnonumber] implements the rules in the September 2003 edition of this publication. You can access the SWIFT Web site at https://go.microsoft.com/fwlink/?LinkId=27885.
Validation errors
There are some codes which are defined by A4SWIFT. These error codes are used in the validation/network rules created and implemented by A4SWIFT, so there is no corresponding error code defined by SWIFT for such rules. Below table shows the error code and corresponding case in which the error is thrown. is the particular field which throws the error.
Error Code | Description |
---|---|
A4SWIFT001 | The first character of multiline field cannot be ‘:’ or ‘-‘ character for second and subsequent lines. |
A4SWIFT002 | Field contains invalid value. |
[!NOTE]
[!INCLUDEA4SWIFT_CurrentVersion_FirstRef] includes support for some legacy messages, because internal applications might use these messages. Therefore, A4SWIFT maintains the associated SWIFT rules and error codes.
More good info
Troubleshooting: Issues and Resolutions
Known Issues
Common terms and definitions
Обработка ошибок
Обработка ошибок — это процесс реагирования на возникновение ошибок и восстановление после появления ошибок в программе. Swift предоставляет первоклассную поддержку при генерации, вылавливании и переносе ошибок, устранении ошибок во время выполнения программы.
Некоторые операции не всегда гарантируют полное выполнение или конечный результат. Опционалы используются для обозначения отсутствия значения, но когда случается сбой, важно понять, что вызвало сбой, для того, чтобы соответствующим образом изменить код.
В качестве примера, рассмотрим задачу считывания и обработки данных из файла на диске. Задача может провалиться по нескольким причинам, в том числе: файл не существует по указанному пути, или файл не имеет разрешение на чтение, или файл не закодирован в необходимом формате. Отличительные особенности этих различных ситуаций позволяют программе решать некоторые ошибки самостоятельно и сообщать пользователю какие ошибки она не может решить сама.
Отображение и генерация ошибок
В Swift ошибки отображаются значениями типов, которые соответствуют протоколу Error. Этот пустой протокол является индикатором того, что это перечисление может быть использовано для обработки ошибок.
Перечисления в Swift особенно хорошо подходят для группировки схожих между собой условий возникновения ошибок и соответствующих им значений, что позволяет получить дополнительную информацию о природе самой ошибки. Например, вот как отображаются условия ошибки работы торгового автомата внутри игры:
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
Генерация ошибки позволяет указать, что произошло что-то неожиданное и обычное выполнение программы не может продолжаться. Для того чтобы «сгенерировать» ошибку, вы используете инструкцию throw. Например, следующий код генерирует ошибку, указывая, что пять дополнительных монет нужны торговому автомату:
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
Обработка ошибок
Когда генерируется ошибка, то фрагмент кода, окружающий ошибку, должен быть ответственным за ее обработку: например, он должен исправить ее, или испробовать альтернативный подход, или просто информировать пользователя о неудачном исполнении кода.
В Swift существует четыре способа обработки ошибок. Вы можете передать (propagate) ошибку из функции в код, который вызывает саму эту функцию, обработать ошибку, используя инструкцию do-catch, обработать ошибку, как значение опционала, или можно поставить утверждение, что ошибка в данном случае исключена. Каждый вариант будет рассмотрен далее.
Когда функция генерирует ошибку, последовательность выполнения вашей программы меняется, поэтому важно сразу обнаружить место в коде, которое может генерировать ошибки. Для того, чтобы выяснить где именно это происходит, напишите ключевое слово try — или варианты try? или try!— до куска кода, вызывающего функцию, метод или инициализатор, который может генерировать ошибку. Эти ключевые слова описываются в следующем параграфе.
Заметка
Обработка ошибок в Swift напоминает обработку исключений (exceptions) в других языках, с использованием ключевых слов try, catch и throw. В отличие от обработки исключений во многих языках, в том числе и в Objective-C- обработка ошибок в Swift не включает разворачивание стека вызовов, то есть процесса, который может быть дорогим в вычислительном отношении. Таким образом, производительные характеристики инструкции throw сопоставимы с характеристиками оператора return.
Передача ошибки с помощью генерирующей функции
Чтобы указать, что функция, метод или инициализатор могут генерировать ошибку, вам нужно написать ключевое слово throws в реализации функции после ее параметров. Функция, отмеченная throws называется генерирующей функцией. Если у функции установлен возвращаемый тип, то вы пишете ключевое слово throws перед стрелкой возврата (->).
func canThrowErrors() throws -> String
func cannotThrowErrors() -> String
Генерирующая функция передает ошибки, которые возникают внутри нее в область вызова этой функции.
Заметка
Только генерирующая ошибку функция может передавать ошибки. Любые ошибки, сгенерированные внутри non-throwing функции, должны быть обработаны внутри самой функции.
В приведенном ниже примере VendingMachine класс имеет vend(itemNamed: ) метод, который генерирует соответствующую VendingMachineError, если запрошенный элемент недоступен, его нет в наличии, или имеет стоимость, превышающую текущий депозит:
struct Item {
var price: Int
var count: Int
}
class VendingMachine {
var inventory = [
"Candy Bar": Item(price: 12, count: 7),
"Chips": Item(price: 10, count: 4),
"Pretzels": Item(price: 7, count: 11)
]
var coinsDeposited = 0
func vend(itemNamed name: String) throws {
guard let item = inventory[name] else {
throw VendingMachineError.invalidSelection
}
guard item.count > 0 else {
throw VendingMachineError.outOfStock
}
guard item.price <= coinsDeposited else {
throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
}
coinsDeposited -= item.price
var newItem = item
newItem.count -= 1
inventory[name] = newItem
print("Dispensing (name)")
}
}
Реализация vend(itemNamed: ) метода использует оператор guard для раннего выхода из метода и генерации соответствующих ошибок, если какое-либо требование для приобретения закуски не будет выполнено. Потому что инструкция throw мгновенно изменяет управление программой, и выбранная позиция будет куплена, только если все эти требования будут выполнены.
Поскольку vend(itemNamed: ) метод передает все ошибки, которые он генерирует, вызывающему его коду, то они должны быть обработаны напрямую, используя оператор do-catch, try? или try!, или должны быть переданы дальше. Например, buyFavoriteSnack(person:vendingMachine: ) в примере ниже — это тоже генерирующая функция, и любые ошибки, которые генерирует метод vend(itemNamed: ), будут переноситься до точки, где будет вызываться функция buyFavoriteSnack(person:vendingMachine: ).
let favoriteSnacks = [
"Alice": "Chips",
"Bob": "Licorice",
"Eve": "Pretzels"
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
try vendingMachine.vend(itemNamed: snackName)
}
В этом примере, функция buyFavoriteSnack(person:vendingMachine: ) подбирает любимые закуски данного человека и пытается их купить, вызывая vend(itemNamed: ) метод. Поскольку метод vend(itemNamed: ) может сгенерировать ошибку, он вызывается с ключевым словом try перед ним.
Генерирующие ошибку инициализаторы могут распространять ошибки таким же образом, как генерирующие ошибку функции. Например, инициализатор структуры PurchasedSnack в списке ниже вызывает генерирующую ошибку функции как часть процесса инициализации, и он обрабатывает любые ошибки, с которыми сталкивается, путем распространения их до вызывающего его объекта.
struct PurchasedSnack {
let name: String
init(name: String, vendingMachine: VendingMachine) throws {
try vendingMachine.vend(itemNamed: name)
self.name = name
}
}
Обработка ошибок с использованием do-catch
Используйте инструкцию do-catch для обработки ошибок, запуская блок кода. Если выдается ошибка в коде условия do, она соотносится с условием catch для определения того, кто именно сможет обработать ошибку.
Вот общий вид условия do-catch:
do {
try выражение
выражение
} catch шаблон 1 {
выражение
} catch шаблон 2 where условие {
выражение
} catch шаблон 3, шаблон 4 where условие {
выражение
} catch {
выражение
}
Вы пишете шаблон после ключевого слова catch, чтобы указать какие ошибки могут обрабатываться данным пунктом этого обработчика. Если условие catch не имеет своего шаблона, то оно подходит под любые ошибки и связывает ошибки к локальной константе error. Более подробно о соответствии шаблону см. Шаблоны.
Например, следующий код обрабатывает все три случая в перечислении VendingMachineError, но все другие ошибки должны быть обработаны окружающей областью:
var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
} catch VendingMachineError.invalidSelection {
print("Ошибка выбора.")
} catch VendingMachineError.outOfStock {
print("Нет в наличии.")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
print("Недостаточно средств. Пожалуйста вставьте еще (coinsNeeded) монетки.")
} catch {
print("Неожиданная ошибка: (error).")
}
// Выведет "Недостаточно средств. Пожалуйста вставьте еще 2 монетки.
В приведенном выше примере, buyFavoriteSnack(person:vendingMachine: ) функция вызывается в выражении try, потому что она может сгенерировать ошибку. Если генерируется ошибка, выполнение немедленно переносится в условия catch, которые принимают решение о продолжении передачи ошибки. Если ошибка не генерируется, остальные операторы do выполняются.
В условии catch не нужно обрабатывать все возможные ошибки, которые может вызвать код в условии do. Если ни одно из условий catch не обрабатывает ошибку, ошибка распространяется на окружающую область. Однако распространяемая ошибка должна обрабатываться некоторой внешней областью. В функции nonthrowing условие включения do-catch должно обрабатывать ошибку. В функции throwing либо включающая условие do-catch, либо вызывающая сторона должна обрабатывать ошибку. Если ошибка распространяется на область верхнего уровня без обработки, вы получите ошибку исполнения.
Например, приведенный ниже пример можно записать так, чтобы любая ошибка, которая не является VendingMachineError, вместо этого захватывалась вызывающей функцией:
func nourish(with item: String) throws {
do {
try vendingMachine.vend(itemNamed: item)
} catch is VendingMachineError {
print("Некорректный вывод, нет в наличии или недостаточно денег.")
}
}
do {
try nourish(with: "Beet-Flavored Chips")
} catch {
print("Unexpected non-vending-machine-related error: (error)")
}
// Выведет "Некорректный вывод, нет в наличии или недостаточно денег."
В nourish(with: ), если vend(itemNamed : ) выдает ошибку, которая является одним из кейсов перечисления VendingMachineError, nourish(with: ) обрабатывает ошибку, печатая сообщение. В противном случае, nourish(with: ) распространяет ошибку на свое место вызова. Ошибка затем попадает в общее условие catch.
Преобразование ошибок в опциональные значения
Вы можете использовать try? для обработки ошибки, преобразовав ее в опциональное значение. Если ошибка генерируется при условии try?, то значение выражения вычисляется как nil. Например, в следующем коде x и y имеют одинаковые значения и поведение:
func someThrowingFunction() throws -> Int {
// ...
}
let x = try? someThrowingFunction()
let y: Int?
do {
y = try someThrowingFunction()
} catch {
y = nil
}
Если someThrowingFunction() генерирует ошибку, значение x и y равно nil. В противном случае значение x и y — это возвращаемое значение функции. Обратите внимание, что x и y являются опциональными, независимо от того какой тип возвращает функция someThrowingFunction().
Использование try? позволяет написать краткий код обработки ошибок, если вы хотите обрабатывать все ошибки таким же образом. Например, следующий код использует несколько попыток для извлечения данных или возвращает nil, если попытки неудачные.
func fetchData() -> Data? {
if let data = try? fetchDataFromDisk() { return data }
if let data = try? fetchDataFromServer() { return data }
return nil
}
Запрет на передачу ошибок
Иногда вы знаете, что функции throw или методы не сгенерируют ошибку во время исполнения. В этих случаях, вы можете написать try! перед выражением для запрета передачи ошибки и завернуть вызов в утверждение того, что ошибка точно не будет сгенерирована. Если ошибка на самом деле сгенерирована, вы получите сообщение об ошибке исполнения.
Например, следующий код использует loadImage(atPath: ) функцию, которая загружает ресурс изображения по заданному пути или генерирует ошибку, если изображение не может быть загружено. В этом случае, поскольку изображение идет вместе с приложением, сообщение об ошибке не будет сгенерировано во время выполнения, поэтому целесообразно отключить передачу ошибки.
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
Установка действий по очистке (Cleanup)
Вы используете оператор defer для выполнения набора инструкций перед тем как исполнение кода оставит текущий блок. Это позволяет сделать любую необходимую очистку, которая должна быть выполнена, независимо от того, как именно это произойдет — либо он покинет из-за сгенерированной ошибки или из-за оператора, такого как break или return. Например, вы можете использовать defer, чтобы удостовериться, что файл дескрипторов закрыт и выделенная память вручную освобождена.
Оператор defer откладывает выполнение, пока не происходит выход из текущей области. Этот оператор состоит из ключевого слова defer и выражений, которые должны быть выполнены позже. Отложенные выражения могут не содержать кода, изменяющего контроль исполнения изнутри наружу, при помощи таких операторов как break или return, или просто генерирующего ошибку. Отложенные действия выполняются в обратном порядке, как они указаны, то есть, код в первом операторе defer выполняется после кода второго, и так далее.
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
defer {
close(file)
}
while let line = try file.readline() {
// работаем с файлом.
}
// close(file) вызывается здесь, в конце зоны видимости.
}
}
Приведенный выше пример использует оператор defer, чтобы удостовериться, что функция open(_: ) имеет соответствующий вызов и для close(_: ).
Заметка
Вы можете использовать оператор defer, даже если не используете кода обработки ошибок.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
Обработка ошибок — это процесс реагирования и исправления ошибок в вашей программе. Swift обеспечивает первоклассную поддержку для генерации, перехвата, распространения и обработки исправляемых ошибок во время выполнения.
Некоторые операции не всегда гарантируют завершение выполнения или получение полезного результата. Необязательные параметры используются для представления отсутствия значения, но когда происходит сбой операции, часто полезно понять, что вызвало сбой, чтобы ваш код мог реагировать соответствующим образом.
В качестве примера рассмотрим задачу чтения и обработки данных из файла на диске. Эта задача может быть выполнена несколькими способами, включая файл, не существующий по указанному пути, файл, не имеющий разрешений на чтение, или файл, не закодированный в совместимом формате. Различение между этими различными ситуациями позволяет программе устранять некоторые ошибки и сообщать пользователю о любых ошибках, которые она не может устранить.
ЗАМЕТКА
Обработка ошибок в Swift взаимодействует с шаблонами обработки ошибок, которые используют
NSError
класс в Какао и Objective-C.
Представление и бросание ошибок
В Swift ошибки представлены значениями типов, которые соответствуют Error
протоколу. Этот пустой протокол указывает, что тип может использоваться для обработки ошибок.
Перечисления Swift особенно хорошо подходят для моделирования группы связанных состояний ошибок с соответствующими значениями, позволяющими передавать дополнительную информацию о природе ошибки. Например, вот как вы можете представить условия ошибки работы торгового автомата в игре:
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
Выдача ошибки позволяет вам указать, что произошло что-то неожиданное, и нормальный поток выполнения не может продолжаться. Вы используете throw
заявление, чтобы выбросить ошибку. Например, следующий код выдает ошибку, чтобы указать, что торговому автомату необходимо пять дополнительных монет:
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
Обработка ошибок
Когда выдается ошибка, некоторый окружающий фрагмент кода должен отвечать за обработку ошибки — например, путем исправления проблемы, попытки альтернативного подхода или информирования пользователя о сбое.
Существует четыре способа обработки ошибок в Swift. Вы можете распространять ошибку из функции в код, который вызывает эту функцию, обрабатывать ошибку с помощью оператора do
— catch
, обрабатывать ошибку как необязательное значение или утверждать, что ошибка не произойдет. Каждый подход описан в разделе ниже.
Когда функция выдает ошибку, она меняет поток вашей программы, поэтому важно, чтобы вы могли быстро определить места в вашем коде, которые могут выдавать ошибки. Чтобы определить эти места в вашем коде, напишите try
ключевое слово ( try?
или try!
вариант или) перед фрагментом кода, который вызывает функцию, метод или инициализатор, который может вызвать ошибку. Эти ключевые слова описаны в разделах ниже.
ЗАМЕТКА
Обработка ошибок в Swift напоминает обработку исключений в других языках, с использованием
try
,catch
иthrow
ключевых слов. В отличие от обработки исключений во многих языках, включая Objective-C, обработка ошибок в Swift не включает в себя разматывание стека вызовов, процесс, который может быть вычислительно дорогим. Таким образом, рабочие характеристикиthrow
оператора сопоставимы с характеристикамиreturn
оператора.
Распространение ошибок с использованием бросающих функций
Чтобы указать, что функция, метод или инициализатор могут выдать ошибку, вы пишете throws
ключевое слово в объявлении функции после ее параметров. Функция с пометкой throws
называется функцией броска . Если функция указывает тип возвращаемого значения, вы пишете throws
ключевое слово перед стрелкой возврата ( ->
).
func canThrowErrors() throws -> String
func cannotThrowErrors() -> String
Функция выброса распространяет ошибки, которые выбрасываются внутри нее, в область, из которой она вызывается.
ЗАМЕТКА
Только бросающие функции могут распространять ошибки. Любые ошибки, возникающие в неработающей функции, должны обрабатываться внутри функции.
В приведенном ниже примере VendingMachine
класс имеет vend(itemNamed:)
метод, который выбрасывает соответствующее значение, VendingMachineError
если запрошенный элемент недоступен, отсутствует на складе или имеет стоимость, превышающую текущую сумму депозита:
struct Item {
var price: Int
var count: Int
}
class VendingMachine {
var inventory = [
"Candy Bar": Item(price: 12, count: 7),
"Chips": Item(price: 10, count: 4),
"Pretzels": Item(price: 7, count: 11)
]
var coinsDeposited = 0
func vend(itemNamed name: String) throws {
guard let item = inventory[name] else {
throw VendingMachineError.invalidSelection
}
guard item.count > 0 else {
throw VendingMachineError.outOfStock
}
guard item.price <= coinsDeposited else {
throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
}
coinsDeposited -= item.price
var newItem = item
newItem.count -= 1
inventory[name] = newItem
print("Dispensing (name)")
}
}
Реализация vend(itemNamed:)
метода использует guard
операторы для раннего выхода из метода и выдачи соответствующих ошибок, если какое-либо из требований для покупки закуски не выполнено. Поскольку throw
оператор немедленно передает управление программой, элемент будет продаваться, только если все эти требования будут выполнены.
Поскольку vend(itemNamed:)
метод распространяется любые ошибки , он бросает, любой код , который вызывает этот метод должен либо обрабатывать ошибки, используя do
— catch
заявление, try?
или try!
-или продолжают их распространять. Например, buyFavoriteSnack(person:vendingMachine:)
в приведенном ниже примере также есть функция throwing, и любые ошибки, которые vend(itemNamed:)
генерирует метод, будут распространяться вплоть до точки, где buyFavoriteSnack(person:vendingMachine:)
вызывается функция.
let favoriteSnacks = [
"Alice": "Chips",
"Bob": "Licorice",
"Eve": "Pretzels",
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
try vendingMachine.vend(itemNamed: snackName)
}
В этом примере функция ищет любимую закуску данного человека и пытается купить ее, вызвав метод. Поскольку метод может выдать ошибку, он вызывается с ключевым словом перед ним.buyFavoriteSnack(person: vendingMachine:)
vend(itemNamed:)
vend(itemNamed:)
try
Бросающие инициализаторы могут распространять ошибки так же, как и бросающие функции. Например, инициализатор для PurchasedSnack
структуры в приведенном ниже листинге вызывает функцию выброса как часть процесса инициализации и обрабатывает любые возникающие ошибки, передавая их вызывающей стороне.
struct PurchasedSnack {
let name: String
init(name: String, vendingMachine: VendingMachine) throws {
try vendingMachine.vend(itemNamed: name)
self.name = name
}
}
Обработка ошибок с помощью Do-Catch
Вы используете оператор do
— catch
для обработки ошибок, выполняя блок кода. Если код в do
предложении выдает ошибку , он сопоставляется с catch
предложениями, чтобы определить, какой из них может обработать ошибку.
Вот общая форма do
— catch
заявление:
do {
try expression
statements
} catch pattern 1 {
statements
} catch pattern 2 where condition {
statements
} catch {
statements
}
Вы пишете шаблон после, catch
чтобы указать, какие ошибки может обработать это предложение. Если catch
предложение не имеет шаблона, оно сопоставляется с любой ошибкой и связывает ошибку с локальной константой с именем error
.
Например, следующий код соответствует всем трем случаям VendingMachineError
перечисления.
var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
print("Success! Yum.")
} catch VendingMachineError.invalidSelection {
print("Invalid Selection.")
} catch VendingMachineError.outOfStock {
print("Out of Stock.")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
print("Insufficient funds. Please insert an additional (coinsNeeded) coins.")
} catch {
print("Unexpected error: (error).")
}
// Prints "Insufficient funds. Please insert an additional 2 coins."
В приведенном выше примере buyFavoriteSnack(person:vendingMachine:)
функция вызывается в try
выражении, поскольку она может выдать ошибку. Если выдается ошибка, выполнение немедленно переходит к catch
предложениям, которые решают, следует ли продолжить распространение. Если ни один шаблон не сопоставлен, ошибка попадает в заключительное catch
предложение и связывается с локальной error
константой. Если ошибка не выдана, остальные операторы в do
операторе выполняются.
Предложения catch
не должны обрабатывать каждую возможную ошибку, которую do
может выдать код в предложении. Если ни одно из catch
предложений не обрабатывает ошибку, ошибка распространяется на окружающую область. Однако распространяемая ошибка должна быть обработана некоторой окружающей областью. В функции nonthrowing, объемлющий do
— catch
пункт должен обработать ошибку. В функции метательного, либо вшита do
— catch
пункт или вызывающий должен обработать ошибку. Если ошибка распространяется на область верхнего уровня без обработки, вы получите ошибку во время выполнения.
Например, приведенный выше пример может быть написан так, что любая ошибка, которая не VendingMachineError
является, вместо этого перехватывается вызывающей функцией:
func nourish(with item: String) throws {
do {
try vendingMachine.vend(itemNamed: item)
} catch is VendingMachineError {
print("Invalid selection, out of stock, or not enough money.")
}
}
do {
try nourish(with: "Beet-Flavored Chips")
} catch {
print("Unexpected non-vending-machine-related error: (error)")
}
// Prints "Invalid selection, out of stock, or not enough money."
В nourish(with:)
функции, если vend(itemNamed:)
выдает ошибку, которая является одним из случаев VendingMachineError
перечисления, nourish(with:)
обрабатывает ошибку, печатая сообщение. В противном случае nourish(with:)
распространяет ошибку на свой сайт вызова. Ошибка тогда поймана общим catch
предложением.
Преобразование ошибок в необязательные значения
Вы используете try?
для обработки ошибки путем преобразования ее в необязательное значение. Если при вычислении try?
выражения выдается ошибка , значением выражения является nil
. Например, в следующем коде x
и y
имеют то же значение и поведение:
func someThrowingFunction() throws -> Int {
// ...
}
let x = try? someThrowingFunction()
let y: Int?
do {
y = try someThrowingFunction()
} catch {
y = nil
}
Если someThrowingFunction()
выдает ошибку, значение x
и y
есть nil
. В противном случае значение x
и y
является значением, которое вернула функция. Обратите внимание, что x
и y
являются необязательными для любого типа someThrowingFunction()
возврата. Здесь функция возвращает целое число, поэтому x
и y
являются необязательными целыми числами.
Использование try?
позволяет вам написать краткий код обработки ошибок, когда вы хотите обрабатывать все ошибки одинаково. Например, следующий код использует несколько подходов для извлечения данных или возвращает, nil
если все подходы дают сбой.
func fetchData() -> Data? {
if let data = try? fetchDataFromDisk() { return data }
if let data = try? fetchDataFromServer() { return data }
return nil
}
Отключение распространения ошибок
Иногда вы знаете, что бросающая функция или метод на самом деле не будут выдавать ошибку во время выполнения. В таких случаях вы можете написать try!
перед выражением, чтобы отключить распространение ошибок, и обернуть вызов в утверждение времени выполнения, что не будет выдано никакой ошибки. Если на самом деле выдается ошибка, вы получите ошибку во время выполнения.
Например, в следующем коде используется loadImage(atPath:)
функция, которая загружает ресурс изображения по заданному пути или выдает ошибку, если изображение не может быть загружено. В этом случае, поскольку образ поставляется с приложением, во время выполнения не будет выдано никаких ошибок, поэтому целесообразно отключить распространение ошибок.
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
Указание действий по очистке
Вы используете defer
оператор для выполнения набора операторов непосредственно перед тем, как выполнение кода покидает текущий блок кода. Этот оператор позволяет выполнять любую необходимую очистку, которая должна выполняться независимо от того, как выполнение покидает текущий блок кода — независимо от того, была ли вызвана ошибка или из-за оператора, такого как return
или break
. Например, вы можете использовать defer
инструкцию, чтобы гарантировать, что файловые дескрипторы закрыты, а выделенная вручную память освобождена.
defer
Заявление отсрочивает выполнение , пока текущая область не закрывается. Этот оператор состоит из defer
ключевого слова и операторов, которые будут выполнены позже. Отложенные операторы могут не содержать какой-либо код, который передавал бы управление из операторов, таких как оператор a break
или return
, или путем выдачи ошибки. Отложенные действия выполняются в порядке, обратном порядку их написания в исходном коде. То есть код в первом defer
операторе выполняется последним, код во втором defer
операторе выполняется со второго до последнего и так далее. Последний defer
оператор в порядке исходного кода выполняется первым.
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
defer {
close(file)
}
while let line = try file.readline() {
// Work with the file.
}
// close(file) is called here, at the end of the scope.
}
}
В приведенном выше примере используется defer
оператор, чтобы гарантировать, что open(_:)
функция имеет соответствующий вызов close(_:)
.
ЗАМЕТКА
Вы можете использовать
defer
оператор, даже если код обработки ошибок не используется.
Error handling is the process of responding to and recovering from error conditions in your program. Swift provides first-class support for throwing, catching, propagating, and manipulating recoverable errors at runtime.
Some operations aren’t guaranteed to always complete execution or produce a useful output. Optionals are used to represent the absence of a value, but when an operation fails, it’s often useful to understand what caused the failure, so that your code can respond accordingly.
As an example, consider the task of reading and processing data from a file on disk. There are a number of ways this task can fail, including the file not existing at the specified path, the file not having read permissions, or the file not being encoded in a compatible format. Distinguishing among these different situations allows a program to resolve some errors and to communicate to the user any errors it can’t resolve.
Representing and Throwing Errors¶
In Swift, errors are represented by values of types that conform to the Error
protocol. This empty protocol indicates that a type can be used for error handling.
Swift enumerations are particularly well suited to modeling a group of related error conditions, with associated values allowing for additional information about the nature of an error to be communicated. For example, here’s how you might represent the error conditions of operating a vending machine inside a game:
- enum VendingMachineError: Error {
- case invalidSelection
- case insufficientFunds(coinsNeeded: Int)
- case outOfStock
- }
Throwing an error lets you indicate that something unexpected happened and the normal flow of execution can’t continue. You use a throw
statement to throw an error. For example, the following code throws an error to indicate that five additional coins are needed by the vending machine:
- throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
Handling Errors¶
When an error is thrown, some surrounding piece of code must be responsible for handling the error—for example, by correcting the problem, trying an alternative approach, or informing the user of the failure.
There are four ways to handle errors in Swift. You can propagate the error from a function to the code that calls that function, handle the error using a do
—catch
statement, handle the error as an optional value, or assert that the error will not occur. Each approach is described in a section below.
When a function throws an error, it changes the flow of your program, so it’s important that you can quickly identify places in your code that can throw errors. To identify these places in your code, write the try
keyword—or the try?
or try!
variation—before a piece of code that calls a function, method, or initializer that can throw an error. These keywords are described in the sections below.
Note
Error handling in Swift resembles exception handling in other languages, with the use of the try
, catch
and throw
keywords. Unlike exception handling in many languages—including Objective-C—error handling in Swift doesn’t involve unwinding the call stack, a process that can be computationally expensive. As such, the performance characteristics of a throw
statement are comparable to those of a return
statement.
Propagating Errors Using Throwing Functions¶
To indicate that a function, method, or initializer can throw an error, you write the throws
keyword in the function’s declaration after its parameters. A function marked with throws
is called a throwing function. If the function specifies a return type, you write the throws
keyword before the return arrow (->
).
- func canThrowErrors() throws -> String
- func cannotThrowErrors() -> String
A throwing function propagates errors that are thrown inside of it to the scope from which it’s called.
Note
Only throwing functions can propagate errors. Any errors thrown inside a nonthrowing function must be handled inside the function.
In the example below, the VendingMachine
class has a vend(itemNamed:)
method that throws an appropriate VendingMachineError
if the requested item isn’t available, is out of stock, or has a cost that exceeds the current deposited amount:
- struct Item {
- var price: Int
- var count: Int
- }
- class VendingMachine {
- var inventory = [
- «Candy Bar»: Item(price: 12, count: 7),
- «Chips»: Item(price: 10, count: 4),
- «Pretzels»: Item(price: 7, count: 11)
- ]
- var coinsDeposited = 0
- func vend(itemNamed name: String) throws {
- guard let item = inventory[name] else {
- throw VendingMachineError.invalidSelection
- }
- guard item.count > 0 else {
- throw VendingMachineError.outOfStock
- }
- guard item.price <= coinsDeposited else {
- throw VendingMachineError.insufficientFunds(coinsNeeded: item.price — coinsDeposited)
- }
- coinsDeposited -= item.price
- var newItem = item
- newItem.count -= 1
- inventory[name] = newItem
- print(«Dispensing (name)«)
- }
- }
The implementation of the vend(itemNamed:)
method uses guard
statements to exit the method early and throw appropriate errors if any of the requirements for purchasing a snack aren’t met. Because a throw
statement immediately transfers program control, an item will be vended only if all of these requirements are met.
Because the vend(itemNamed:)
method propagates any errors it throws, any code that calls this method must either handle the errors—using a do
—catch
statement, try?
, or try!
—or continue to propagate them. For example, the buyFavoriteSnack(person:vendingMachine:)
in the example below is also a throwing function, and any errors that the vend(itemNamed:)
method throws will propagate up to the point where the buyFavoriteSnack(person:vendingMachine:)
function is called.
- let favoriteSnacks = [
- «Alice»: «Chips»,
- «Bob»: «Licorice»,
- «Eve»: «Pretzels»,
- ]
- func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
- let snackName = favoriteSnacks[person] ?? «Candy Bar»
- try vendingMachine.vend(itemNamed: snackName)
- }
In this example, the buyFavoriteSnack(person: vendingMachine:)
function looks up a given person’s favorite snack and tries to buy it for them by calling the vend(itemNamed:)
method. Because the vend(itemNamed:)
method can throw an error, it’s called with the try
keyword in front of it.
Throwing initializers can propagate errors in the same way as throwing functions. For example, the initializer for the PurchasedSnack
structure in the listing below calls a throwing function as part of the initialization process, and it handles any errors that it encounters by propagating them to its caller.
- struct PurchasedSnack {
- let name: String
- init(name: String, vendingMachine: VendingMachine) throws {
- try vendingMachine.vend(itemNamed: name)
- self.name = name
- }
- }
Handling Errors Using Do-Catch¶
You use a do
—catch
statement to handle errors by running a block of code. If an error is thrown by the code in the do
clause, it’s matched against the catch
clauses to determine which one of them can handle the error.
Here is the general form of a do
—catch
statement:
- do {
- try expression
- statements
- } catch pattern 1 {
- statements
- } catch pattern 2 where condition {
- statements
- } catch pattern 3, pattern 4 where condition {
- statements
- } catch {
- statements
- }
You write a pattern after catch
to indicate what errors that clause can handle. If a catch
clause doesn’t have a pattern, the clause matches any error and binds the error to a local constant named error
. For more information about pattern matching, see Patterns.
For example, the following code matches against all three cases of the VendingMachineError
enumeration.
- var vendingMachine = VendingMachine()
- vendingMachine.coinsDeposited = 8
- do {
- try buyFavoriteSnack(person: «Alice», vendingMachine: vendingMachine)
- print(«Success! Yum.»)
- } catch VendingMachineError.invalidSelection {
- print(«Invalid Selection.»)
- } catch VendingMachineError.outOfStock {
- print(«Out of Stock.»)
- } catch VendingMachineError.insufficientFunds(let coinsNeeded) {
- print(«Insufficient funds. Please insert an additional (coinsNeeded) coins.»)
- } catch {
- print(«Unexpected error: (error).»)
- }
- // Prints «Insufficient funds. Please insert an additional 2 coins.»
In the above example, the buyFavoriteSnack(person:vendingMachine:)
function is called in a try
expression, because it can throw an error. If an error is thrown, execution immediately transfers to the catch
clauses, which decide whether to allow propagation to continue. If no pattern is matched, the error gets caught by the final catch
clause and is bound to a local error
constant. If no error is thrown, the remaining statements in the do
statement are executed.
The catch
clauses don’t have to handle every possible error that the code in the do
clause can throw. If none of the catch
clauses handle the error, the error propagates to the surrounding scope. However, the propagated error must be handled by some surrounding scope. In a nonthrowing function, an enclosing do
—catch
statement must handle the error. In a throwing function, either an enclosing do
—catch
statement or the caller must handle the error. If the error propagates to the top-level scope without being handled, you’ll get a runtime error.
For example, the above example can be written so any error that isn’t a VendingMachineError
is instead caught by the calling function:
- func nourish(with item: String) throws {
- do {
- try vendingMachine.vend(itemNamed: item)
- } catch is VendingMachineError {
- print(«Couldn’t buy that from the vending machine.»)
- }
- }
- do {
- try nourish(with: «Beet-Flavored Chips»)
- } catch {
- print(«Unexpected non-vending-machine-related error: (error)«)
- }
- // Prints «Couldn’t buy that from the vending machine.»
In the nourish(with:)
function, if vend(itemNamed:)
throws an error that’s one of the cases of the VendingMachineError
enumeration, nourish(with:)
handles the error by printing a message. Otherwise, nourish(with:)
propagates the error to its call site. The error is then caught by the general catch
clause.
Another way to catch several related errors is to list them after catch
, separated by commas. For example:
- func eat(item: String) throws {
- do {
- try vendingMachine.vend(itemNamed: item)
- } catch VendingMachineError.invalidSelection, VendingMachineError.insufficientFunds, VendingMachineError.outOfStock {
- print(«Invalid selection, out of stock, or not enough money.»)
- }
- }
The eat(item:)
function lists the vending machine errors to catch, and its error text corresponds to the items in that list. If any of the three listed errors are thrown, this catch
clause handles them by printing a message. Any other errors are propagated to the surrounding scope, including any vending-machine errors that might be added later.
Converting Errors to Optional Values¶
You use try?
to handle an error by converting it to an optional value. If an error is thrown while evaluating the try?
expression, the value of the expression is nil
. For example, in the following code x
and y
have the same value and behavior:
- func someThrowingFunction() throws -> Int {
- // …
- }
- let x = try? someThrowingFunction()
- let y: Int?
- do {
- y = try someThrowingFunction()
- } catch {
- y = nil
- }
If someThrowingFunction()
throws an error, the value of x
and y
is nil
. Otherwise, the value of x
and y
is the value that the function returned. Note that x
and y
are an optional of whatever type someThrowingFunction()
returns. Here the function returns an integer, so x
and y
are optional integers.
Using try?
lets you write concise error handling code when you want to handle all errors in the same way. For example, the following code uses several approaches to fetch data, or returns nil
if all of the approaches fail.
- func fetchData() -> Data? {
- if let data = try? fetchDataFromDisk() { return data }
- if let data = try? fetchDataFromServer() { return data }
- return nil
- }
Disabling Error Propagation¶
Sometimes you know a throwing function or method won’t, in fact, throw an error at runtime. On those occasions, you can write try!
before the expression to disable error propagation and wrap the call in a runtime assertion that no error will be thrown. If an error actually is thrown, you’ll get a runtime error.
For example, the following code uses a loadImage(atPath:)
function, which loads the image resource at a given path or throws an error if the image can’t be loaded. In this case, because the image is shipped with the application, no error will be thrown at runtime, so it’s appropriate to disable error propagation.
- let photo = try! loadImage(atPath: «./Resources/John Appleseed.jpg»)
Specifying Cleanup Actions¶
You use a defer
statement to execute a set of statements just before code execution leaves the current block of code. This statement lets you do any necessary cleanup that should be performed regardless of how execution leaves the current block of code—whether it leaves because an error was thrown or because of a statement such as return
or break
. For example, you can use a defer
statement to ensure that file descriptors are closed and manually allocated memory is freed.
A defer
statement defers execution until the current scope is exited. This statement consists of the defer
keyword and the statements to be executed later. The deferred statements may not contain any code that would transfer control out of the statements, such as a break
or a return
statement, or by throwing an error. Deferred actions are executed in the reverse of the order that they’re written in your source code. That is, the code in the first defer
statement executes last, the code in the second defer
statement executes second to last, and so on. The last defer
statement in source code order executes first.
- func processFile(filename: String) throws {
- if exists(filename) {
- let file = open(filename)
- defer {
- close(file)
- }
- while let line = try file.readline() {
- // Work with the file.
- }
- // close(file) is called here, at the end of the scope.
- }
- }
The above example uses a defer
statement to ensure that the open(_:)
function has a corresponding call to close(_:)
.
Note
You can use a defer
statement even when no error handling code is involved.
Мы используем обработку ошибок с помощью do-try-catch для реагирования на исправимые ошибки. Это дает нам больший контроль над различными ошибочными сценариями, которые могут возникнуть в нашем коде, например, при вводе неправильного имени пользователя или пароля.
Зачем нужно отслеживать ошибки?
В приложении некоторые ошибки могут быть результатом ошибок программиста. Когда ваше приложение вылетает с сообщением «Index out of bounds», вы, вероятно, где-то допустили ошибку. И точно так же, когда вы принудительно извлекаете опциональное значение, которое имеет значение nil, ваше приложение падает.
В практической разработке iOS некоторые ошибки являются частью работы приложения, например, сообщение «Недостаточно средств» при попытке оплаты с помощью карты.
Ошибки такого рода исправимы. Их можно обработать и отреагировать соответствующим образом. К примеру:
- При попытке снять деньги в банкомате отображается «Неверный PIN-код».
- Ваш автомобиль показывает индикатор низкого уровня топлива при попытке запустить двигатель.
- Попытка аутентификации для API возвращает «Неверное имя пользователя / пароль».
Вы можете работать с этими ошибками, отобразив сообщение с предупреждением или сделав что-то еще. Например, ваша карта блокируется после 3 неудачных попыток. Ваш автомобиль может указать вам ближайшую заправку, когда у вас кончается бензин. Вы можете попробовать ввести другое имя пользователя и пароль.
Swift поддерживает обработку ошибок с помощью блока кода do-try-catch.
Выбрасывание ошибок
Когда в вашем коде возникает сценарий, который может привести к ошибке, вы можете выбросить ошибку:
if fuel < 1000 { throw RocketError.insufficientFuel }
В приведенном выше коде ключевое слово throw используется для выдачи ошибки типа RocketError.insufficientFuel, когда переменная fuel меньше, чем 1000.
Представьте, что мы пытаемся запустить ракету:
func igniteRockets(fuel: Int, astronauts: Int) throws { if fuel < 1000 { throw RocketError.insufficientFuel } else if astronauts < 3 { throw RocketError.insufficientAstronauts(needed: 3) } // Запуск ракеты print("3... 2... 1... Старт!") }
Функция igniteRockets(fuel:astronauts:) будет запускать ракеты, только если значение fuel больше или равно 1000 и если на борту есть как минимум 3 астронавта.
Функция igniteRockets(…) также помечается ключевым словом throws. Это ключевое слово указывает, что ошибки должны быть обработаны.
В приведенном выше коде мы используем тип ошибки RocketError:
enum RocketError: Error { case insufficientFuel case insufficientAstronauts(needed: Int) case unknownError }
Данное перечисление определяет три типа ошибок: .insufficientFuel, insufficientAstronauts(needed) и .unknownError. Определение ваших собственных типов ошибок полезно, потому что это поможет четко понять, что эти ошибки означают в вашем коде.
Возьмем, например, ошибку insufficientAstronauts(needed:). Когда выдается эта ошибка, вы можете использовать аргумент needed:, который указывает, сколько астронавтов необходимо для успешного запуска ракеты.
Ключевое слово throw имеет тот же эффект, что и ключевое слово return. Когда выполняется throw, выполнение функции останавливается, и выброшенная ошибка передается вызывающей функции.
Теперь мы можем использовать обработку ошибок, чтобы соответствующим образом реагировать на сценарии ошибок. Обработка ошибок в Swift осуществляется с помощью блока кода do-try-catch:
do { try igniteRockets(fuel: 5000, astronauts: 1) } catch { print(error) }
Обработка ошибок имеет три аспекта:
- К функции, которая может вызвать ошибку, добавляется ключевое слово try.
- Блок кода, который включает ключевое слово try, обернут в do { … }.
- Один или несколько блоков catch { … } могут быть присоединены к do { … } для обработки отдельных случаев ошибок.
Если функция выдает ошибку, вызывается блок catch. В данном случае это выводит ошибку на консоль.
Вы также можете реагировать на ошибки в индивидуальном порядке:
do { try igniteRockets(fuel: 5000, astronauts: 1) } catch RocketError.insufficientFuel { print("Ракете нужно больше топлива!") } catch RocketError.insufficientAstronauts(let needed) { print("Нужно как минимум (needed) астронавта...") }
Вышеуказанные блоки catch вызываются на основании отдельных перечислений RocketError. Вы можете напрямую получить доступ к связанным значениям перечислений, таких как needed. Также вы можете использовать выражения с шаблоном where чтобы получить больший контроль над ошибочным сценарием.
enum RocketError: Error { case insufficientFuel case insufficientAstronauts(needed: Int) case unknownError } func igniteRockets(fuel: Int, astronauts: Int) throws { if fuel < 1000 { throw RocketError.insufficientFuel } else if astronauts < 3 { throw RocketError.insufficientAstronauts(needed: 3) } // Ignite rockets print("3... 2... 1... Полет!") } do { try igniteRockets(fuel: 5000, astronauts: 1) } catch { print(error) }
Преобразование ошибок в опционалы с помощью try?
Целью обработки ошибок является явное определение того, что происходит при возникновении ошибки. Это позволяет нам реагировать определенным образом на ошибки.
В некоторых случаях нас не волнует сама ошибка. Нам просто нужно получить значение из функции. И если возникает ошибка, мы можем возвратить nil. Эта возможность доступна с помощью ключевого слова try? Когда вы используете try?, вам не нужно использовать полный блок кода do-try-catch.
let result = try? calculateValue(for: 42)
Представьте, что функция может выбрасывать ошибки, если ее параметр недействителен. Вместо обработки ошибки мы конвертируем возвращаемое значение в опциональное.
Возможны два сценария:
- Функция не выдает ошибку и возвращает значение, которое присваивается константе result.
- Функция выдает ошибку и не возвращает значение. Это означает, что константе result присваивается nil.
Обработка ошибок с помощью try? означает, что вы можете воспользоваться синтаксисом, специфичным для опционалов, таких как объединение по nil и опциональное связывание:
if let result = try? calculateValue(for: 99) { // } let result = try? calculateValue(for: 123) ?? 101
Отключение обработки ошибок с помощью try!
Вы можете полностью отключить обработку ошибок с помощью try!. Ключевое слово try! используется для принудиального извлечения опционального значения.
В отличие от того try?, который возвращает опциональное значение, синтаксис try! приведет к сбою вашего кода в случае возникновения ошибки. Есть два различных сценария, в которых использование try! может быть полезно:
- Используйте try!, когда вы на 100% уверенны, что ошибка не возникнет.
- Используйте, try!, когда невозможно продолжить выполнение кода.
Представьте, что вы пишите приложение, в которое встроен файл базы данных. Функция загрузки базы данных выдает ошибку, когда база данных повреждена. Вы можете использовать try! для загрузки базы данных в память, потому что, если база данных повреждена, приложение все равно не сможет быть использовано.
Search code, repositories, users, issues, pull requests…
Provide feedback
Saved searches
Use saved searches to filter your results more quickly
Sign up
-
Messaging
FIN
Error CodesThis reference guide lists the error codes and abort
notifications returned by FIN in case of message validation errors
orother conditions such as protocol violations or delivery
issues.22 July 2011
-
Table of Contents
Preface………………………………………………………………………………………………………………………………….
4About this document
……………………………………………………………………………………………………………
4Audience
……………………………………………………………………………………………………………………………
4Significant
changes……………………………………………………………………………………………………………..
4Chapter 1 Introduction
…………………………………………………………………………………………………………….
6Chapter 2 Numeric Codes
……………………………………………………………………………………………………….
72.1 General
………………………………………………………………………………………………………………………..
72.2 Logout/Quit Acknowledgement Errors
………………………………………………………………………………
72.3 Re-Login Request Errors
………………………………………………………………………………………………..
72.4 Retrieval Errors
……………………………………………………………………………………………………………..
82.5 Message Status
…………………………………………………………………………………………………………..
102.6 Abort Reasons
…………………………………………………………………………………………………………….
122.7 FIN and General Purpose Application Session
Termination……………………………………………….
132.8 Report Errors
………………………………………………………………………………………………………………
142.9 Bulk Retrieval Errors
Codes…………………………………………………………………………………………..
15Chapter 3 Alphanumeric
Codes………………………………………………………………………………………………
163.1 General
………………………………………………………………………………………………………………………
163.2 A Codes — Re-select Error Codes
…………………………………………………………………………………..
163.3 B Codes — Copy Service
Errors………………………………………………………………………………………
163.4 C, D, and E Codes — Conditional Semantic Error Codes
…………………………………………………… 173.5 G Codes — Service-specific
Validation……………………………………………………………………………
1563.6 H Codes — Basic Header and Application Header Validation
……………………………………………. 1583.7 K Codes — Code Words Validation in Generic Fields
……………………………………………………….
1593.8 L Codes — LOGIN Errors
……………………………………………………………………………………………..
1603.9 M Codes — Message Errors
………………………………………………………………………………………….
1603.10 P Codes — Protocol Errors
………………………………………………………………………………………….
1613.11 R Codes — Re-login/Re-select Errors
…………………………………………………………………………..
1623.12 S Codes — System-initiated Abort Errors
………………………………………………………………………
1623.13 S Codes — Select Errors
…………………………………………………………………………………………….
1633.14 T Codes — Text Validation
………………………………………………………………………………………….
1653.15 U Codes — User Header
Validation………………………………………………………………………………
1803.16 V Codes — System Message Errors and Message Block Format
Errors …………………………… 1803.17 X Codes — FINCopy Message Validation (01 — 27) and Delayed
NAK Error Codes (30 — 99) . 183FIN
2 Error Codes
-
3.18 Y Codes — UNK Error Codes
………………………………………………………………………………………
1853.19 Z Codes — Trailer Validation
……………………………………………………………………………………….
185Chapter 4 FIN
Errors……………………………………………………………………………………………………………
1864.1 Introduction
……………………………………………………………………………………………………………….
1864.2 Abort Codes
………………………………………………………………………………………………………………
1864.3 Diagnostic Codes for
SS100………………………………………………………………………………………..
1884.4 Diagnostic Codes for
SA100………………………………………………………………………………………..
190Legal Notices
……………………………………………………………………………………………………………………..
194Table of Contents
22 July 2011 3
-
Preface
About this documentThis reference guide lists the error codes
and abort notifications returned by FIN in case of message
validationerrors or other conditions such as protocol violations or
delivery issues.AudienceThis book describes the FIN Error Codes. It should be
read by:users who wish to gain an understanding of the FIN service
developers who need background information on elements of
FINThe reader is expected to have an understanding of FIN
messaging, which is described in the FIN ServiceDescription and the
FIN Operations Guide.Significant changesThe following tables list all significant
changes to the content of the FIN Error Codes since the 23 July
2010edition. These tables do not include editorial changes that
SWIFT makes to improve the usability andcomprehension of the
document.New information Location
Addition of MTs 670 in error codes C05, D08, D09,D11, D12, D13,
D14, D15, E23, E84, T19, T73, T85,and T86Error codes C05, D08, D09, D11, D12, D13, D14,D15, E23, E84,
T19, T73, T85, and T86Addition of MTs 380 and 381 in error code D13 Error code D13
Addition of message status 29 Section 2.5, Message Status
Addition of abort reason code 29 Section 2.6, Abort Reasons
Explanation regarding code S1 Section 2.6, Abort Reasons
Addition of report errors 006, 007, 008, 009, and 016 Section
2.8, Report ErrorsAddition of error codes M78, M79, M80, and M81 Section 3.9, M
Codes — Message ErrorsNew FIN errors chapter Chapter 4, FIN Errors
Updated information Location
Update text of message statuses 31, 32, 33, 34, 35,37, 38
Section 2.5, Message Status
FIN
4 Error Codes
-
Updated information Location
Update text of error codes B03, C28, C59, C71, E06,E08, E09,
E22, E62, E77, E78, E80, E83, E87, E98,M73, T14, T39, T62, T73, and
U03Section 3.3, B Codes — Copy Service Errors
Section 3.4.1, C Error Codes
Section 3.4.3, E Error Codes
Section 3.9, M Codes — Message Errors
Section 3.14, T Codes — Text Validation
Section 3.15, U Codes — User Header Validation
Error codes D87, D88, D89, D90, D91, D94, D95,E63, E75, E88,
E89, E98, and V26 again available Section 3.4.2, D Error CodesSection 3.4.3, E Error Codes
Section 3.16, V Codes — System Message Errorsand Message Block
Format ErrorsDeleted information Location
Deletion of references to MTs 405, 528, 529, 582,584, 587, 588,
and 589Changes apply throughout the document
Deletion of section 3.2 A Codes — Abort atApplication Interface
Level following thedeimplementation of Application Interface in
FINChapter 3, Alphanumeric Codes
Deletion of section 3.17 U Codes — User Abort Codes Chapter 3,
Alphanumeric CodesPreface
22 July 2011 5
-
Chapter 1 IntroductionThe FIN error codes are divided into the
following groups:Validation error codes
Conditional semantic error codes
Abort error codes
All input messages are validated for syntax and semantic errors
by the system. If there is an error, a validationerror code is
returned in the logical (negative) acknowledgement or in an MT 019
Abort Notification.Abort error codes give the reason why an application or the
logical connection has been discontinued. Theyare generated
following the recognition of a certain condition and not
necessarily due to errors in a message.Abort error codes can come
from the system or from a user’s terminal.For reference purposes, the error codes have been placed in two
chapters. Chapter 2, Numeric Codes,contains all the errors that are
represented by two- or three-digit codes. Error codes in Chapter
3,Alphanumeric Codes, have the following format:where is a letter designating the error type and identifies the
particular error.FIN
6 Error Codes
-
Chapter 2 Numeric Codes
2.1 GeneralNumeric codes are used for:
Logout/Quit Acknowledgement errors (field 401)
Re-Login Request errors (fields 280, 331 and 333)
Retrieval errors (field 421)
Message status (field 431)
Abort reasons (field 432)
FIN and General Purpose Application session termination (field
443)Report errors (field 461)
2.2 Logout/Quit Acknowledgement ErrorsThe following error codes
are returned in field 401 of Logout and Quit acknowledgements.
Logout and QuitCommands are always positively acknowledged and the
session (General Purpose Application or FIN) closed.However, one of
the following error codes can be included in the
acknowledgement.01 Incorrect time/dayThe Logout Command can include the time/day
inhibitor which prevents the next Loginoccurring before the
time/day specified. The time/day in the format DDHHMM cannot be
morethan 7 days after the current date.02 Training trailer missingThe trailer block is only present if
the message is sent by a training logical terminal. If the
LogoutCommand is sent from a training logical terminal, it must
contain a Training trailer.03 Input sequence number errorEach message sent from a logical
terminal has an input sequence number. The first messagesent in the
General Purpose Application will always have an input sequence
number of 000001,whereas the first message sent in FIN will have an
input sequence number value of the lastinput sequence number+1 sent
from that logical terminal. This error will be returned in
theacknowledgement of a Logout or Quit Command when the input
sequence number of thatcommand is incorrect.2.3 Re-Login Request ErrorsThe following error codes are
returned in fields 280, 331, and 333 of acknowledgements, session
historyreports, and daily check reports:010 Re-Login Request received while logical terminal is active
on the Logical Terminal ControlassociationChapter 2 Numeric Codes
22 July 2011 7
-
011 Logical Terminal Control state error, unable to recover the
logical terminal session012 Re-Login Request authentication failed
013 Re-Login Request semantic error
014 Re-Login Request format error
015 Re-Login Request login request number is incorrect
016 Multiple Re-Logins from user
017 Re-Login Request received while the logical terminal is in
unrecoverable state019 Re-Login Request, session recovery information: incorrect
General Purpose Application sessionnumber020 Re-Login Request, session recovery information: incorrect
input sequence number021 Re-Login Request, session recovery information: input
sequence number-ACK greater thaninput sequence number022 Re-Login Request, session recovery information: input
sequence number-ACK less than thelower bound023 Re-Login Request, session recovery information: incorrect
output sequence number024 Re-Login Request, session recovery information: incorrect
window size026 Re-Login Request, login and re-login protocol versions are
not the same027 Re-Login Request, logical terminal does not belong to Sign
Distinguished Name (DN)organisation028 Re-Login Request, the Live destination that owns the Test
and Training destination does notbelong to Sign Distinguished Name
(DN) organisation2.4 Retrieval ErrorsThe following codes are returned in field
421 of message retrievals:000 Message has no text block
002 Message was encrypted and no key or the wrong key was
supplied by the userFIN
8 Error Codes
-
003 Empty report (no messages found)
004 Logical terminal is not authorised to retrieve the message,
that is the requester is neither thesender nor the receiver of the
original message005 Text lost due to Slice Processor recovery
006 History lost due to Slice Processor recovery
007 Target message is a retrieval report (MTs 021 or 023)
010 Invalid MT received by Slice Processor pseudo logical
terminal (system)011 Invalid received by Slice Processor pseudo logical terminal
(system)012 Invalid date in retrieval criteria tag (system)
013 Invalid time in retrieval criteria tag (system)
014 End daytime before start daytime
015 Target message older than 124 days (for range retrieval,
daytime used)016 is not ‘XXX’
018 Invalid destination for report (tag 102). The logical
terminal must have the same destination asthe sender of the
retrieval request or be a SWIFT logical terminal, and must be
enabled for theapplication in which the retrieval message is to be
sent019 Invalid input retrieval by receiver or output retrieval by
sender (only single message inputreference/message output reference
allowed)020 Invalid synonym retrieval (synonym is not sender or receiver
of message)021 Unknown target logical terminal
022 Request received at wrong Slice Processor (system)
023 Could not retrieve message input reference in message output
reference retrieval (system)032 No delivery attempt in message input reference retrieval by
receiver033 On-line text read error (system)
034 On-line history read error (system)
Chapter 2 Numeric Codes
22 July 2011 9
-
035 Text read error from archival (system)
036 History read error from archival (system)
037 Partial report — major system recovery in progress
038 Unable to retrieve text and history from archival because of
system problems040 The limits for group retrieval (99 messages in one request)
have been exceeded041 Message could not be decrypted (system)
043 The logical terminals in the beginning message input
reference/message output reference andthe ending message input
reference/message output reference in a range retrieval request
arenot the same, in tag 252 (message input reference range) or 254
(message output referencerange)044 Illogical use of field 152 or field 153 . input sequence
number or outputsequence number already included as component in
message input reference(s) or messageoutput reference(s)045 Message text not retrievable (message not successfully
delivered)046 Off-line retrieval not allowed for Test and Training
messages047 The text of local test mode messages is not retrievable
048 Retrieval message too long
049 Retrieval period specified exceeds 10 days
099 Retrieval report problem. Contact your Customer Support
Centre2.5 Message StatusThe message status is returned in field 431 of
non-delivery warnings, undelivered message reports, andretrieved
messages.01 Delivered
02 Rejected by destinee
04 Aborted
FIN
10 Error Codes
-
07 No delivery attempt
08 One or more unsuccessful attempts
10 Message not delivered (that is no delivery history) for one
of the following reasons:Message negatively acknowledged on input
Message is Login, Select, Quit or Logout Request
Message was sent in local test mode (not deliverable)
Message is MT 097 (processed directly by Slice Processor and
never delivered to anylogical terminal, and so does not have a
delivery history)12 Intercepted
29 Message held for approval prior to Bypass mode and
aborted31 Authorised by the copy service or Sanctions Screening over
SWIFT service subscriber anddelivered32 Not authorised by the copy service or Sanctions Screening
over SWIFT service subscriber andaborted by the system33 Copy message is aborted and not delivered to the copy
service34 Authorised by the copy service or Sanctions Screening over
SWIFT service subscriber butaborted by the system35 Not yet authorised/refused by the copy service or Sanctions
Screening over SWIFT servicesubscriber37 Authorised by the copy service or Sanctions Screening over
SWIFT service subscriber but nodelivery attempted38 Authorised by the copy service or Sanctions Screening over
SWIFT service subscriber but oneor more unsuccessful delivery
attempts41 Copy service bypassed and message delivered
44 Copy service bypassed but message aborted by the system
47 Copy service bypassed but no delivery attempted
48 Copy service bypassed but one or more unsuccessful delivery
attempts49 Refused by central institution. Abort notification MT 019
contains an alphanumeric abort codeChapter 2 Numeric Codes
22 July 2011 11
-
50-99 These codes are specific to each FINCopy service. Contact
your respective service provider forthe meaning of each code within
the range 50-99.For Euro Banking Association (EBA) Processing, only the
following codes are used:70 Refusal from the Clearing Computer, and delivery aborted; the
Sender of thepayment message should also receive an MT 998 / SMT
n75 Error Message fromthe Clearing Computer giving further reasons
for the refusal.71 Refusal from the Clearing Computer because of a message
format error thatprevented normal processing, and delivery
aborted.99 System error
2.6 Abort ReasonsThe following codes are returned in field 432
of abort notifications and, for the FINCopy service,
MessageRefusals:01 Message too old (remained undelivered for n days)
02 Too many unsuccessful delivery attempts
03 Destination disabled
04 Operator aborted
05 Message could not be recovered after a major system failure
because it was user encrypted06 Message type incompatible with computer-based terminal
mode11 Message is too old, but was authorised
12 Too many delivery attempts, but message was authorised
13 Destination is disabled, but message was authorised
14 Message is too long, but was authorised
21 Message is too old and was bypassed
22 Too many delivery attempts and the message was bypassed
23 Destination is disabled and the message was bypassed
24 Message is too long and was bypassed
FIN
12 Error Codes
-
Note:
29 Message held for approval prior to Bypass mode and
aborted32 Message is too old and was not authorised
33 Copy message to the copy service server was aborted
35 FINCopy service parameter(s) incorrectly defined in FIN
50-ZZ 99 is pre-defined as ‘system error’.All other alphanumeric
codes (combination of 0-9 and A-Z) are specific to each
FINCopyservice. Contact your respective service provider for the
meaning of each code.Code S1 is used by the Sanctions screening service to indicate
that the message has beenaborted on request of the subscribing
user.All undefined numeric codes are reserved for use by FIN.
2.7 FIN and General Purpose Application Session TerminationThe
following codes are returned in field 443 of Service Message 14
(for further details see the FIN SystemMessages):000 Normal termination
001 Application Control or Logical Terminal Control has
aborted002 Application Control or Logical Terminal Control has
terminated normally004 System timed out message output reference ACK
006 QUIT or LOGOUT received while outstanding input messages
007 Input message/Service message after reception of a QUIT or
LOGOUT008 Input window violation (more outstanding input messages than
window size)009 System timed out on association establishment
010 Reception of a SELECT from a logical terminal that already
has a FIN session011 Association establishment request failed authentication
014 Message output reference ACK Basic Header error
015 Too many messages input in a session. Maximum is 500000.
Chapter 2 Numeric Codes
22 July 2011 13
-
016 Too many messages output in a session. Maximum is
500000.020 Message output reference ACK from wrong synonym
025 As for 052 but due to receipt of a Re-Login Request, rather
than a Login Request051 As for 052 but on a different Regional Processor
052 Reception of a login from a logical terminal for which the
system has already processed a logintransmitted over a different
Logical Terminal Control on the same Regional Processor.
Theexisting session is aborted and the new session established.053 SELECT with bad text block
054 AP ABORT REQUEST with bad text block
2.8 Report ErrorsThe following codes are returned in field 461
of Delivery Subset Status Reports, Undelivered MessageReports, and
Undelivered SSI Update Notification Reports:001 Empty report
002 End of undelivered report
003 System undergoing major recovery or system not completely
synchronised yet004 Too many undelivered messages
005 User on fall back Regional Processor, cannot generate
report006 The message referenced in the request could not be
found.007 Invalid destination for report. The sender of the request
must be the same as the sender of themessage referenced in the
request.008 No MTs 671 were found for the referenced MT 670.
009 Requesting logical terminal in invalid state
016 Branch code is not «XXX’
099 System internal problems, contact your Customer Support
CentreFIN
14 Error Codes
-
2.9 Bulk Retrieval Errors CodesThe following codes are returned
in field 144 of Bulk Retrieval Responses (MT 025):03 Retrieval only partially complete
11 Invalid
12 Invalid
13 Invalid retrieval time range
14 Retrieval aborted due to system error
15 Retrieval aborted due to communication error
16 Retrieval aborted by SWIFT
19 Retrieval completeThe text of messages that were sent to the
retrieving BIC more than 124 days ago cannot beretrieved. If those
messages were received by the retrieving BIC less than 124 days
ago, the filecontains the message output reference of the history
and the message input reference of thetext.20 Retrieval aborted due to system error (Test and Training
destination — attempt to use tape)21 Retrieval aborted due to system error (FIN/FIN Bridge key
error)22 Retrieval aborted due to system error (missing master
BIC)Chapter 2 Numeric Codes
22 July 2011 15
-
Note:
Note:
Chapter 3 Alphanumeric Codes
3.1 GeneralThis chapter contains the codes for the following
error types:Code Error Type Code Error Type
A Abort at Application Interface Level Errors R
Re-login/Re-select ErrorsA Re-select Errors S System-initiated Abort Errors
B Copy Service Errors S Select Errors
C Dialout Errors T Text validation (Block 4) Errors
C, Dand E
Conditional Semantic Errors U User Header Validation Errors
G Service-specific Validation Errors U User Abort Errors
H Basic Header and Application HeaderValidation Errors
V System Message or Message BlockFormat Errors
K Code Words Errors in Generic Fields X Delayed NAK Errors and
FINCopyService Message RefusalsL LOGIN Errors Y User Negative Acknowledgement Errors
M Message Errors Z Trailer Validation Errors
P Protocol Errors
Similar error codes are used by other SWIFT services, such as
Accord, or Processing forEuro Banking Association (EBA), and can
have different meanings. The error codes used byeach of the
services are described in the respective service documentation.3.2 A Codes — Re-select Error CodesA56 Re-select NAK error code
(in field tag 503) to indicate that the logical terminal is not in
arecoverable state. The computer-based terminal should execute a
fresh select procedure.3.3 B Codes — Copy Service ErrorsSimilar error codes are used by
other SWIFT services, such as Accord, or Processing forEuro Banking Association (EBA), and can have different meanings.
The error codes used byeach of the services are described in the
respective service documentation.B01 Message contains Value-Added Service server id but sender or
receiver, or both, are notmembers of the service.B02 Available.
FIN
16 Error Codes
-
B03 103:TPS is present in the message but the sender is not a
member of TPS, or the message isnot allowed for TPS.B04 Available.
B05 Either a system error has occurred, in which case, the user
should contact its local CustomerSupport Centre for further
information or it was not possible to generate a copy message
asnone of the fields to be copied were present in the original
message.3.4 C, D, and E Codes — Conditional Semantic Error CodesNote
Where a natural language expression would be too difficult to
synthesise or too long, amatrix is provided. The row and column
headers identify the elements involved (forexample, field tags,
code words, letter options). Matrices should be read from left
toright and from top to bottom. The following abbreviations are
used:M = Mandatory (must be present)
O = Optional (may be present)
U = Unauthorised (must not be present)
Y = Yes (is present)
N = No (is not present)
NA = Not applicable
3.4.1 C Error Codes
C00 Not used.
C01 MTs 102, 102+, 104, and 107If field 19 is present in
sequence C, then it must equal the sum of the amounts in all
occurrencesof field 32B in sequence B.MTs 201, 203, 204, and 559The amount in field 19 must equal the
sum of the amounts in all occurrences of field 32B or 34A.MT 256If field 19 is present in sequence C, then it must equal
the sum of the amounts in all occurrencesof field 32J in sequence
B.MT 824Field 19 at the completion of each outer repetitive
sequence must equal the sum of the productsof subfields 1 and 3 in
all occurrences of field 68A from its respective inner
repetitivesequence(s).Chapter 3 Alphanumeric Codes
22 July 2011 17
-
C02 The currency code must be the same for all occurrences of
indicated fields in the entiremessage. See the SWIFT Standards
Category volumes for the indicated fields in eachmessage.Examples:
The following list explains how Error code C02 is applied in
specific message types:MT 321. The currency code in the amount fields (fields 19A in
sequence B) must be thesame for all occurrences of this field in
the message.MTs 320 and 330. The currency code in the amount fields, except
for fields 33B and 33E insequence G, must be the same for all
occurrences of these fields in the message.MT 350. The currency code in the amount fields 32B and 34B in
sequence B must be thesame.Special Cases:
The following MTs apply Error code C02 in an exceptional manner
(for example, either based onthe presence of another field OR
individually to separate groups of fields within the MT):MTs 103 and 103+. If field 71G is present, the currency code in
the fields 71G and 32Amust be the same.MTs 104 and 107. The currency code in fields 32B and 71 G in
sequences B and C must bethe same for all occurrences of these
fields in the message. The currency code in field 71Fin sequences B
and C must be the same for all occurrences of this field in the
message.MT 320. The currency codes in the amount fields 32B, 32H, and
34E in sequence B, andfield 71F in sequence H, must be the
same.MT 620. If field 32H is present, then the currency code must be
the same as the currencycode in field 32B.C03 The number of decimal digits in the amount component is
checked against the maximumallowed for the corresponding currency.
This check is mostly applied to fields containing boththe amount
and the currency code components.Examples:
field 32A in MT 103, and in MT 256, sequence C
field 32B in MTs 104 and 107, sequences B and C
This check also applies, among others, to:
field 19 in MTs 102, 104, 107, 201, 203, 204, and 559 where the
corresponding currency isthe one used in field 32B or 34Afield 19 in MT 824 where the corresponding currency is the one
used in correspondingoccurrences of field 68Afield 32J in sequence B, and to field 19 in sequence C, in MT
256 where the correspondingcurrency is the one used in field
32Afield 33B in MT 103, and in MTs 104 and 107, sequence B
field 71F in MT 103, and in MTs 104 and 107, sequences B and
Cfield 71G in MT 103, and in MTs 104 and 107, sequences B and
Cfield 72 Reject/Return in MT 103, and in MTs 104 and 107,
sequence AFIN
18 Error Codes
-
Note:
Note:
Error code C03 should be applied only to field 68A in MT 824 if
subfield 5 ispresent.C04 MTs 503, 504, and 506In sequence B, if field :19B::TEXA is
not present, then field :19B::TCRL is mandatory; otherwisefield
:19B::TCRL is optional.Sequence B
If field :19B::TEXA is … Then field :19B::TCRL is …
Not present Mandatory
Present Optional
C05 Identifier Code must be a financial institution BIC. This
error code applies to all types of BICsreferenced in a FIN message,
including SWIFT BICs, Non-SWIFT BICs, Masters, Synonyms,Live
destinations and Test & Training destinations.See the table below for the list of MTs affected.
MT Field Sequence(s) Qualifier Comments
52A A, B
56A B
101
57A B
52A A, B
53A C
54A C
102
57A B
The same validation applies to thegeneric MT 102 without tag
119,and the MT 102+52A
53A
54A
55A
56A
103
57A
The same validation applies to thegeneric MT 103 without tag
119,and other variants, such as the MT103 REMIT and the MT 103+52A A, B
53A C
104
57A B
The same validation applies to thegeneric MT 104 without tag
119,and the MT 104 RFDDFor sequence C, seeError code C96.
52A A, B
53A C
107
57A B
Chapter 3 Alphanumeric Codes
22 July 2011 19
-
MT Field Sequence(s) Qualifier Comments
52A
53A
110
54A
111,112
52A
56A200,201
57A
52A
53A
54A
56A
57A
202,203
58A
52A A
53A A
54A A
56A A
57A A
58A A
52A B
56A B
202COV
57A B
53A B
57A A
204
58A A
52A
53A
56A
57A
205
58A
FIN
20 Error Codes
-
MT Field Sequence(s) Qualifier Comments
52A A
53A A
56A A
57A A
58A A
52A B
56A B
205COV
57A B
51A A
52A A
52G A
56A B
57A B
207
58A B
52A210
56A
256 57A C
53AJ B1, B2, D
56AJ B1, B2, D
300
57AJ B1, B2, D
53AJ D1, D2, D3
56AJ D1, D2, D3
303
57AJ D1, D2, D3
53AJ B, E
56AJ B, E
304
57AJ B, E
53A
56A
305
57A
Chapter 3 Alphanumeric Codes
22 July 2011 21
-
MT Field Sequence(s) Qualifier Comments
53AJ C, E, J
56AJ C, E, J
57AJ C, E, J
84AJ B
306
86AJ C, E, J
95P B3a CDEA INTE ACCW307
95P D1 CDEA INTE ACCW
53AJ C, D, E, F, I
56AJ C, D, E, F, I
57AJ C, D, E, F, I
320
86AJ C, D, E, F, I
321 95P C1 CDEA INT2 INTEACCW
53AJ C, D, E, F
56AJ C, D, E, F
57AJ C, D, E, F
330
86AJ C, D, E, F
53AJ C, D, F
56AJ C, D, F
57AJ C, D, F
340
86AJ C, D, F
53AJ C
56AJ C
57AJ C
341,350
86AJ C
53A D, G, L, M
56A D, G, L, M
57A D, G, L, M
360
86A D, G, L, M
FIN
22 Error Codes
-
MT Field Sequence(s) Qualifier Comments
53A D, G, J, K, L,M
56A D, G, J, K, L,M
57A D, G, J, K, L,M
361
86A D, G, J, K, L,M
53A C, E
56A C, E
57A C, E
362
86A C, E
53A L, M
56A L, M
57A L, M
364
86A L, M
53A J, K, L, M
56A J, K, L, M
57A J, K, L, M
365
86A J, K, L, M
52A
53A
54A
57A
400
58A
416 53A A
450,455,456
52A
502 95P C2 ACCW PAYE
504 95P C2a1, E1 ACCW PAYE
505 95P B2a1, D1 ACCW PAYE
507 95P B1b1 ACCW PAYE
513 95P D2 ACCW PAYE
514 95P C2 ACCW PAYE
Chapter 3 Alphanumeric Codes
22 July 2011 23
-
MT Field Sequence(s) Qualifier Comments
515 95P D2 ACCW PAYE
516 57A B
518 95P C2 ACCW PAYE
540,541,542,543,544,545,546,547
95P E2 ACCW PAYE
559 57A
566 95P D2a ACCW
578 95P E2 ACCW PAYE
53A B
56A B, C
57A B, C
86A B, C
600
87A B, C
53A
56A
601
57A
56A
86A
604
87A
86A605
87A
606 87A
607 87A
53AJ C, D, E, F
56AJ C, D, E, F
57AJ C, D, E, F
620
86AJ C, D, E, F
643 57A B, C
644 57A B
646 57A C
FIN
24 Error Codes
-
MT Field Sequence(s) Qualifier Comments
670 95P B1 ACCW INT1 INT2
41A
42A
51A
53A
700
57A
41A705
57A
707 52A
41A
42A
51A
52A
53A
710
57A
41A
42A
52A
720
57A
730,734
57A
41A
42A
740
58A
52A
57A
742
58A
750 57A
53A752
54A
53A
57A
754
58A
Chapter 3 Alphanumeric Codes
22 July 2011 25
-
MT Field Sequence(s) Qualifier Comments
53A756
54A
768,769
57A
51A
52A
53A
800
54A
801 51A
52A
53A
802
54A
824 51A
900 52A
52A910
56A
985 57A
n90 52A
52An91
57A
C06 MT 210Either field 50a or field 52a, but not both, must be
present in a repetitive sequence.MTs 710 and 720Either field 52a or field 50B, but not both, must
be present.If field 52a is … Then field 50B is …
Present Not allowed
Not present Mandatory
MT 910Either field 50a or field 52a, but not both, must be
present.C07 MT 516Either field 35A or 35N must be present.
C08 Available.
FIN
26 Error Codes
-
C09 MT 430In each occurrence of sequence A, if field 33a is
present, then field 32a must be present.C10 MT 422At least one of the fields 72, 75 or 76 must be
present.C11 MT 400If field 57a is present, fields 53a and 54a must be
present.C12 MTs 707 and 747When field 32B or 33B is present, field 34B
must be present. Conversely, when field 34B ispresent, either field
32B or field 33B must be present.C13 MT 750If any of fields 33B, 71B or 73 is present, field 34B
must be present.C14 MTs 559 and 754Either field 53a or 57a, but not both, may be
present.C15 MT 747At least one of the fields 31E, 32B, 33B, 34B, 39A,
39B, 39C, 72 or 77A must be present.C16 MT 707If field 23 is present, field 52a must be present.
C17 MT 734If field 73 is present, field 33a must be present.
C18 MT 752If fields 32B and 71B are present, field 33a must be
present.C19 MT 754Either field 72 or field 77A, but not both, may be
present.C20 MT 601Field 53a may be present only if field 34P is
present.C21 MT 506If sequence C is not present, then sequence D is
mandatory. If one or more occurrence ofsequence C is/are present,
then sequence D is optional.If sequence C is … Then sequence D is …
Not present Mandatory
Chapter 3 Alphanumeric Codes
22 July 2011 27
-
Note:
If sequence C is … Then sequence D is …
Present (once or more) Optional
C22 MT 920If field 12 contains 942, field 34F must be present in
the same repetitive sequence.C23 MTs 920 and 942When only one field 34F is present, subfield
2 must not be used. When both fields 34F arepresent, subfield 2 of
the first 34F must contain D, and subfield 2 of the second 34F
mustcontain C.In MT 920, this applies to each repetitive sequence.
C24 MT 940If field 86 is present in any occurrence of the
repetitive sequence, it must be preceded by a field61.C25 MT n92Field 79 or a copy of at least any fields of the
original message or both must be present.If field 79 is … Then copy of any field(s) of originalmessage
is …Present Optional
Not present Mandatory (that is, minimum one field, anyfield)
SWIFT does not validate the relationship between the copied
fields and theoriginal message, hence, any valid field is correct.
The system will negativelyacknowledge the MT n92 with Error code
C25 if there is no more field after field11S.C26 MT 430At least one of the optional fields 32a or 74 must be
present.C27 MTs 940, 941, 942, 950, 970, and 972The first two characters
of the three-character currency code in fields 60F, 60M, 62F, 62M,
64,65, 90C and 90D, in MTs 940, 941, 942, 950, 970 and 972, and
field 34F in MT 942 must be thesame for all occurrences of these
fields.C28 MT 541, 543, 578A value date must only be provided for
cash/securities split settlement. That is, in anyoccurrence of
subsequence E3, if value date field :98a::VALU is present, then in
sequence Efield :22F::STCO//SPST must be present, and settlement
amount field :19A::SETT must bepresent in the same subsequence
E3.FIN
28 Error Codes
-
Note:
Note:
In any occurrence ofsubsequence E3
if field :98a::VALU is …
Sequence Ethen field
:22F::STCO//SPST (withDSS not present)
In the same occurrence ofsubsequence E3
and field :19A::SETT is …
Present Mandatory Mandatory
Not present Optional Optional
MT 544, 545, 546, 547A value date must only be provided with an
effective settlement amount, that is, in anyoccurrence of
subsequence E3, if value date field :98a::VALU is present, then
settled amountfield :19A::ESTT must be present in the same
subsequence.Subsequence E3if field :98a::VALU is …
Subsequence E3then field :19A::ESTT is …
Present Mandatory
Not present Optional
MTs 544, 545, 546, and 547, see Network Validated Rule 287
(Error codeE87).MTs 545 and 547, see Network Validated Rule 292 (Error code
E92).MT 586A value date must only be provided for cash/securities
split settlement. That is, in anyoccurrence of subsequence B5b, if
value date field :98a::VALU is present, then in subsequenceB5 field
:22F::STCO//SPST must be present, and settlement amount field
:19A::SETT must bepresent in the same subsequence B5b.In any occurrence ofsubsequence B5b
if field :98a::VALU is …
Subsequence B5then field
:22F::STCO//SPST (withDSS not present) is …
In the same occurrence ofsubsequence B5b
and field :19A::SETT is …
Present Mandatory Mandatory
Not present Optional Optional
C29 Available.
C30 MT 707At least one of the fields 31E, 32B, 33B, 34B, 39A,
39B, 39C, 44A, 44E, 44F, 44B, 44C, 44D, 79or 72 must be
present.C31 MTs n95 and n96Either field 79 or a ‘copy of any field(s) of
the original message to which this message relates’,but not both,
may be present.SWIFT does not validate the relationship between the copied
fields and theoriginal message; hence any valid fields other than
79 are accepted.Chapter 3 Alphanumeric Codes
22 July 2011 29
-
C32 MTs 300, 303, 304, 306, 320, 330, 340, 350, 360, 361, 362,
364, 365, 600, 620, and 643An optional sequence of fields was used.
However, a field that is required (that is, indicated byan ‘OR’) or
a field that is mandatory (that is, indicated by ‘Mandatory in
…’) within this sequenceis missing.C33 MTs 768 and 769If field 71B is present, field 32a must be
present.C34 MT 769Either field 33B or 39C, but not both, must be
present.C35 MTs 643, 644, 646, and 649Either field 21 or 29B must be
present.C36 MTs 643 and 646Subfield 2 () of field 31F must be present in
each occurrence of sequence B.C37 MT 577Subfield 2 () of field 67A must not be present.
C38 Available.
C39 Available.
C40 MT 920The currency code must be the same for each occurrence
of the indicated fields within eachrepetitive sequence.C41 Available.
C42 MT 824The currency code in each of the fields 68A of a
sequence of fields 68A preceding a field 19must be the same.C43 MT 646Either field 32N or 33N must be present.
C44 MT 646If fields 32N and 33N are present in sequence C, field
34a must be present in sequence C.C45 MT 646If field 23 contains REPRINC or PREPRINC, field 32N
must be present in sequence C.FIN
30 Error Codes
-
C46 MT 646If field 23 contains INT, field 33N must be present in
sequence C.C47 MT 643If field 23 contains LOAN/DRAWDOWN or FINARR/DRAWDOWN,
sequence B must not bepresent.C48 MT 643If field 23 contains LOAN/RENEWAL or FINARR/RENEWAL,
sequence B must be present.C49 MT 456If field 71B is present, the values in fields 32a and
33D must be different.C50 MTs 540, 541, 542, and 543If field 36B is present in minimum
one occurrence of sequence A1, then the type of
settlementtransaction must be a pair-off or a turn-around, that is,
sequence E field :22F::SETR//PAIR or:22F::SETR//TURN must be
present.In sequence A1if field :36B: is …
Then in sequence Efield :22F::SETR must be …
Present :22F::SETR//PAIR and DSS must not
bepresentor:22F::SETR//TURN and DSS must not bepresentNot present NA
C51 MT 643If field 23 contains LOAN/DRAWDOWN or LOAN/RENEWAL,
field 31R must be present.C52 Available.
C53 MT 643If field 71C is present in any sequence B, field 34a
must be present in the same sequence.C54 MT 644Either field 36 or field 37(A-F) must be present in
any sequence B.C55 MT 644In any sequence B, the currency code in fields 33B and
34a must be the same.C56 Available.
Chapter 3 Alphanumeric Codes
22 July 2011 31
-
C57 MT 646If field 34N is present in any sequence B, field 31F
in the same sequence B and field 33N insequence C must be
present.C58 MT 300In field 77D of sequence A, if the code /VALD/ is
present, then it must appear in the first 6characters of the first
line and in no other place, and it must be followed by a date
expressed asYYYYMMDD and the «end_of_line» separator, that is,
«:77D:/VALD/»YYYMMDD»CrLf».See rule 59.
MT 304In field 72 of sequence C, if the code /VALD/ is present,
then it must appear in the first 6characters of the first line and
in no other place, and it must be followed by a date expressed
asYYYYMMDD and the «end_of_line» separator, that is
«:72:/VALD/»YYYMMDD»CrLf».See rule 59.
MT 646If field 34N is present in any sequence B, the total
amount given in field 33N must equal the totalamount of all
occurrences of field 34N amounts in sequence B.C59 MT 300In sequence A, if field 77D is present and if the
first six (6) characters of the first line are equal to/VALD/, then
the second line must be present and it must contain «/SETC/» in the
first 6characters, followed by a valid ISO 4217 currency code and
the end of line separator, that is,»/SETC/»»CrLf».Conversely, in sequence A, if field 77D is present, and the
second line is present, and the firstsix (6) characters of the
second line are equal to /SETC/, then the first six (6) characters
of thefirst line must be equal to /VALD/.The code «/SETC/» is not allowed in other places than the first
6 characters of the second line.See rule 58.
MT 304In sequence C, if field 72 is present, and the first six
(6) characters of the second line are equalto /SETC/, then the
first six (6) characters of the first line must be equal to /VALD/
and /SETC/must be followed by a valid ISO 4217 currency code and
the end of line separator, that is,»/SETC/»»CrLf».The code «/SETC/» is not allowed in other places than the first
6 characters of the second line.See rule 58.
MT 321In sequence B, the presence of field 19A and of the Next
Interest Due Date (field :98A::INTR)depends on the Type of
Loan/Deposit Event (field :22H::TLDE) in sequence A as follows:In sequenceA
if field:22H::TLDE
Indicatoris …
Sequence Bthen field
:98A::INTRis …
Sequence Band field
:19A::SETTis …
Sequence Band field
:19A::RODIis …
Sequence Band field
:19A::CINTis …
SequenceB
and field:19A::NINT
is …
CONF Mandatory Not allowed Not allowed Not allowed Mandatory
ROLL Mandatory Mandatory Optional Optional Mandatory
FIN
32 Error Codes
-
In sequenceA
if field:22H::TLDE
Indicatoris …
Sequence Bthen field
:98A::INTRis …
Sequence Band field
:19A::SETTis …
Sequence Band field
:19A::RODIis …
Sequence Band field
:19A::CINTis …
SequenceB
and field:19A::NINT
is …
MATU Not allowed Mandatory Not allowed Optional Not allowed
MT 800The amounts in fields 34B and 32A must be the same.
C60 MT 307In sequence A, the presence of field :22H::APER and
the presence of field :22H::NEGR dependon the field :22H::CRTR as
follows:In sequence Aif field :22H::CRTR Indicator
is …
Sequence Athen field :22H::APER is …
Sequence Aand field :22H::NEGR is …
ASET Not allowed Optional
AFWD Mandatory Mandatory
MT 321In sequence A, the presence of field :99B:: depends on the
presence of field :22H::BLOC asfollows:In sequence Aif field :22H::BLOC is …
Sequence Athen field :99B:: is …
Present Mandatory
Not present Not allowed
MT 643In each sequence B, the currency code in fields 32P, 33a
and 34a must be the same.C61 MT 307In sequence A, the presence of field :22H::PAFI
depends on field :22H::APER as follows:In sequence Aif field :22H::APER
Indicator is …
Sequence Athen field :22H::PAFI is …
OPEF Not allowed
NOPE Mandatory
Field :22H::APER not present Not allowed
MT 321In sequence B, the presence of field :98A::LDFP depends on
the value of field :22H::TLDE asfollows:Chapter 3 Alphanumeric Codes
22 July 2011 33
-
In sequence Aif field :22H::TLDE
Indicator is …
Sequence Bthen field :98A::LDFP
is …
MATU Not allowed
Not MATU Optional
MT 643In each sequence C, the currency code in fields 32B and
33B must be the same.C62 MT 307The presence of sequence C depends on field :22H::APER
as follows:In sequence Aif field :22H::APER
Indicator is …
Thensequence C
is …
OPEF Not allowed
NOPE Mandatory
Field :22H::APER not present Not allowed
MT 321In sequence B, the presence of field :99B::DAAC depends on
the presence of field :98A::LDFPas follows:In sequence Bif field :98A::LDFP
is …
Sequence Bthen field :99B::DAAC
is …
Present Mandatory
Not present Not allowed
C63 MT 307In sequence A, the presence of the qualifier UNKN in
field :22H::NEGR//UNKN depends on thecontent of field :22H::CRTR,
of field :22H::APER and of field :22H::PAFI as follows:In sequence Aif field :22H::
is …
Then field:22H::NEGR//UNKN
is …
CRTR//ASET Not allowed
CRTR//AFWD and APER//OPEF Optional
CRTR//AFWD and APER//NOPE andPAFI//PAIN
Optional
CRTR//AFWD and APER//NOPE andPAFI//FINA
Not allowed
MT 321In sequence A, if field 99B is present, then all
qualifiers must be present.FIN
34 Error Codes
-
C64 MT 307The presence of sequence D depends on the value of
field 22H as follows:In sequence A
If field:22H::CRTR
is …
And field:22H::APER
is …
And field:22H::PAFI
is …
And field:22H::NEGR
is …
Thensequence D
is …
ASET NA per rule 60 NA per rule 61 NETC Optional
ASET NA per rule 60 NA per rule 61 GRSC Not allowed
ASET NA per rule 60 NA per rule 61 Not present Not allowed
AFWD OPEF NA per rule 61 NETC or GRSCor UNKN
Not allowed
AFWD NOPE PAIN NETC or GRSCor UNKN
Not allowed
AFWD NOPE FINA NETC Mandatory
AFWD NOPE FINA GRSC Not allowed
C65 MT 567If the message is a cancellation request status
(:23G::CAST), then, in every occurrence ofsequence A2 Status, a
cancellation processing status must be reported
(:25D::CPRC…).If the message is an instruction status (:23G::INST) then, in
every occurrence of sequence A2Status, an instruction processing
status (:25D::IPRC…) must be reported.If the message is corporate action event processing status
(:23G::EVST), then, in everyoccurrence of sequence A2 Status, an
event status (:25D::EPRC…) must be reported.In sequence Aif field 23G is …
Then, in every occurrence of sequence A2Status,
field :25D must be …
CAST :25D::CPRC…
INST :25D::IPRC…
EVST :25D::EPRC…
C66 MT 643The number of occurrences of sequence C must be equal
to or greater than the number ofoccurrences of sequence B.C67 MT 516In sequence A, either field 83C or 87a but not both,
may be present.C68 MTs 202 COV and 205 COVIn sequence B, if field 56a is
present, then field 57a must also be present.Chapter 3 Alphanumeric Codes
22 July 2011 35
-
Note:
C69 MT 507In each occurrence of sequence B, if present, if
subsequence B1 is present, the presence ofsubsequences B1a and B1b
depends on the value of field :22H::COLL in sequence B
asfollows:In each occurrence of sequence B
If subsequence B1is …
And in sequence Bfield
:22H::COLL//Statusis …
Then subsequenceB1a is …
And subsequenceB1b is …
CCOL Not allowed Mandatory
SCOL Mandatory Not allowed
Present
BCOL(NA see Error code
C70)
NA NA
Not present NA NA NA
Rule C70 takes precedence over rule C69.
C70 MT 507In each occurrence of sequence B, the presence of
subsequence B1 depends on the value offields :25D::COLL// and
:22H::COLL// as follows:In each occurrence of sequence B
If field :25D::COLL/[8c]/4!c Data Source
Scheme [8c] is …
And field:25D::COLL/[8c]/4!c
is …
And field:22H::COLL//4!c is …
Then subsequenceB1 is …
:25D::COLL//ACCT BCOL Not allowed
:25D::COLL//ACCT CCOL Mandatory [1]
:25D::COLL//ACCT SCOL Mandatory [1]
Not present
:25D::COLL//REJT NA Not allowed
BCOL Not allowed
CCOL Optional [1]
Present NA
SCOL Optional [1]
[1] See Error code C69 for additional checks. Rule C70 takes
precedence over rule C69.C71 MT 535In each occurrence of subsequence B1, field 93B::AGGR
cannot appear more than twice(maximum 2 occurrences). When
repeated, one occurrence must have Quantity Type CodeFAMT and the
other occurrence must have Quantity Type Code AMOR.FIN
36 Error Codes
-
Subsequence B1if field :93B::AGGR is …
Then one occurrence of:93B:AGGR must be …
And the other occurrenceof :93B::AGGR must be …
Repeated :93B::AGGR//FAMT and DSSmust not be present
:93B::AGGR//AMOR andDSS must not be present
Not repeated NA NA
MT 536In each occurrence of subsequence B1a2, field 36B::PSTA
cannot appear more than twice(maximum 2 occurrences). When
repeated, one occurrence must have Quantity Type CodeFAMT and the
other occurrence must have Quantity Type Code AMOR.Subsequence B1a2if field :36B::PSTA is …
Then one occurrence of:36B::PSTA must be …
And the other occurrenceof :36B::PSTA must be …
Repeated :36B::PSTA//FAMT :36B::PSTA//AMOR
Not repeated NA NA
MT 537In each occurrence of subsequence B2b, field 36B::PSTA
cannot appear more than twice(maximum 2 occurrences). When
repeated, one occurrence must have Quantity Type CodeFAMT and the
other occurrence must have Quantity Type Code AMOR.Subsequence B2bif field :36B::PSTA is …
Then one occurrence of:36B::PSTA must be …
And the other occurrenceof :36B::PSTA must be …
Repeated :36B::PSTA//FAMT :36B::PSTA//AMOR
Not repeated NA NA
MTs 540, 541, 542, and 543In sequence C, field 36B::SETT cannot
appear more than twice (maximum 2 occurrences).When repeated, one
occurrence must have Quantity Type Code FAMT and the
otheroccurrence must have Quantity Type Code AMOR.Sequence Cif field :36B::SETT is …
Then one occurrence of:36B::SETT must be …
And the other occurrenceof :36B::SETT must be …
Repeated :36B::SETT//FAMT :36B::SETT//AMOR
Not repeated NA NA
MTs 544, 545, 546, and 547In sequence C, field 36B::ESTT cannot
appear more than twice (maximum 2 occurrences).When repeated, one
occurrence must have Quantity Type Code FAMT and the
otheroccurrence must have Quantity Type Code AMOR.Sequence Cif field :36B::SETT is …
Then one occurrence of:36B::ESTT must be …
And the other occurrenceof :36B::ESTT must be …
Repeated :36B::ESTT//FAMT :36B::ESTT//AMOR
Not repeated NA NA
MT 548In sequence. B, field 36B::SETT cannot appear more than
twice (maximum 2 occurrences).When repeated, one occurrence must
have Quantity Type Code FAMT and the otheroccurrence must have
Quantity Type Code AMOR.Chapter 3 Alphanumeric Codes
22 July 2011 37
-
Sequence Bif field :36B::SETT is …
Then one occurrence of:36B::SETT must be …
And the other occurrenceof :36B::SETT must be …
Repeated :36B::SETT//FAMT :36B::SETT//AMOR
Not repeated NA NA
MT 564In each occurrence of subsequence B2, field 93B::ELIG
cannot appear more than twice(maximum 2 occurrences). When
repeated, one occurrence must have Quantity Type CodeFAMT and the
other occurrence must have Quantity Type Code AMOR.Subsequence B2if field :93B::ELIG is …
Then one occurrence of:93B:ELIG must be …
And the other occurrenceof :93B::ELIG must be …
Repeated :93B::ELIG//FAMT and DSSmust not be present
:93B::ELIG//AMOR and DSSmust not be present
Not repeated NA NA
MT 565In subsequence B2, field 93B::ELIG cannot appear more than
twice (maximum 2 occurrences).When repeated, one occurrence must
have Quantity Type Code FAMT and the otheroccurrence must have
Quantity Type Code AMOR.Subsequence B2if field :93B::ELIG is …
Then one occurrence of:93B::ELIG must be …
And the other occurrenceof :93B::ELIG must be …
Repeated :93B::ELIG//FAMT and DSSmust not be present
:93B::ELIG//AMOR and DSSmust not be present
Not repeated NA NA
MT 566In sequence B, field 93B::ELIG cannot appear more than
twice (maximum 2 occurrences).When repeated, one occurrence must
have Quantity Type Code FAMT and the otheroccurrence must have
Quantity Type Code AMOR.Sequence Bif field :93B::ELIG is …
Then one occurrence of:93B:ELIG must be …
And the other occurrenceof :93B::ELIG must be …
Repeated :93B::ELIG//FAMT and DSSmust not be present
:93B::ELIG//AMOR and DSSmust not be present
Not repeated NA NA
MT 567In sequence B, field 36B::STAQ or QREC cannot appear more
than twice (maximum 2occurrences). When repeated, one occurrence
must have Quantity Type Code FAMT and theother occurrence must have
Quantity Type Code AMOR.Sequence Bif field :36B::STAQ or QREC
is …
Then one occurrence of:36B:STAQ or QREC must
be …
And the other occurrenceof :36B::STAQ or QRECmust be …
:36B::STAQ//FAMT or :36B::STAQ//AMORRepeated
:36B::QREC//FAMT :36B::QREC//AMOR
Not repeated NA NA
FIN
38 Error Codes
-
MT 568In sequence B, field 93B::ELIG cannot appear more than
twice (maximum 2 occurrences).When repeated, one occurrence must
have Quantity Type Code FAMT and the otheroccurrence must have
Quantity Type Code AMOR.Sequence Bif field :93B::ELIG is …
Then one occurrence of:93B:ELIG must be …
And the other occurrenceof :93B::ELIG must be …
Repeated :93B::ELIG//FAMT and DSSmust not be present
:93B::ELIG//AMOR and DSSmust not be present
Not repeated NA NA
MT 707If field 79 is present, it cannot appear more than twice
(maximum 2 occurrences).C72 MT 537In each occurrence of subsequence C2, field 36B::PSTA
cannot appear more than twice(maximum 2 occurrences). When
repeated, one occurrence must have Quantity Type CodeFAMT and the
other occurrence must have Quantity Type Code AMOR.Subsequence C2if field :36B::PSTA is …
Then one occurrence of:36B::PSTA must be …
And the other occurrenceof :36B::PSTA must be …
Repeated :36B::PSTA//FAMT :36B::PSTA//AMOR
Not repeated NA NA
MT 564In each occurrence of subsequence E1, field 36B::ENTL
cannot appear more than twice(maximum 2 occurrences). When
repeated, one occurrence must have Quantity Type CodeFAMT and the
other occurrence must have Quantity Type Code AMOR.Subsequence E1if field :36B::ENTL is …
Then one occurrence of:36B::ENTL must be …
And the other occurrenceof :36B::ENTL must be …
Repeated :36B::ENTL//FAMT :36B::ENTL//AMOR
Not repeated NA NA
MT 565In sequence. D, field 36B::QINS or QREC cannot appear more
than twice (maximum 2occurrences). When repeated, one occurrence
must have Quantity Type Code FAMT and theother occurrence must have
Quantity Type Code AMOR. When used with format option C,
thequalifiers QINS and QREC cannot be repeated.Sequenceif field :36B::QINS or QREC
is …
Then one occurrence of:36B::QINS or QREC must
be …
And the other occurrenceof :36B::QINS or QRECmust be …
:36B::QINS//FAMT :36B::QINS//AMORRepeated
:36B::QREC//FAMT :36B::QREC//FAMT
Not repeated NA NA
Chapter 3 Alphanumeric Codes
22 July 2011 39
-
Note: Therefore the only valid repetitions are:
:36B::QINS//FAMT
:36B::QINS//AMOR
or
:36B::QREC//FAMT
:36B::QREC//AMOR
MT 566In each occurrence of subsequence D1, field 36B::PSTA
cannot appear more than twice(maximum 2 occurrences). When
repeated, one occurrence must have Quantity Type CodeFAMT and the
other occurrence must have Quantity Type Code AMOR.Subsequence D1if field :36B::PSTA is …
Then one occurrence of:36B::PSTA must be …
And the other occurrenceof :36B::PSTA must be …
Repeated :36B::PSTA//FAMT :36B::PSTA//AMOR
Not repeated NA NA
C73 MT 536A reference to the previously received message must be
specified for each transaction reported,that is, in each occurrence
of subsequence B1a Transaction, field 20C::RELA must be presentin
one and only one occurrence of subsequence B1a1 Linkages; field
20C::RELA is not allowedin all other occurrences of subsequence
B1a1.MT 537A reference to the previously received message must be
specified for each transaction reported,that is, in each occurrence
of subsequence B2 Transaction, field 20C::RELA must be present
inone and only one occurrence of subsequence B2a Linkages; field
20C::RELA is not allowed inall other occurrences of subsequence
B2a.MTs 544, 545, 546, 547, and 548A reference to the previously
received message must be specified, that is, field 20C::RELA mustbe
present in one and only one occurrence of subsequence A1 Linkages;
field 20C::RELA is notallowed in all other occurrences of
subsequence A1.C74 MT 537A reference to the previously received message must be
specified for each transaction reported,that is, in each occurrence
of sequence C Transaction, field 20C::RELA must be present in
oneand only one occurrence of subsequence C1 Linkages; field
20C::RELA is not allowed in allother occurrences of subsequence
C1.C75 MT 104The presence of field 23E in sequence B, depends on
the presence and content of field 23E insequence A as follows:If field 23E is present in sequence A and contains RFDD, then
field 23E must be present inall occurrences of sequence B.If field 23E is present in sequence A and does not contain RFDD,
then field 23E must notbe present in any occurrence of sequence
B.FIN
40 Error Codes
-
Note:
If field 23E is not present in sequence A, then field 23E must
be present in all occurrencesof sequence B.Sequence Aif field 23E is …
Sequence Bif field 23E is …
Present and = RFDD Mandatory in all occurrences
Present and not = RFDD Not allowed
Not present Mandatory in all occurrences
See Error codes C94 and C96.
C76 MT 104Field 50a (option A or K) must be present either in
sequence A or in each occurrence ofsequence B, but must never be
present in both sequences, nor absent from both sequences.Sequence Aif field 50a (option A or K) is …
In every occurrence of sequence B,then field 50 (option A or K)
is …Present Not allowed
Not present Mandatory
C77 MTs 730, 768, and 769Either field 25 or field 57a, but not
both, may be present.C78 MTs 730, 768, and 769Either field 32D or field 57a, but not
both, may be present.C79 MTs 305 and 601Field 31C may be present only if subfield 3
of field 23 contains A.C80 MT 608The commodity code must be the same for all
occurrences of the indicated fields in the entiremessage.C81 MTs 103, 103+, 202, 202 COV (sequence A), 203, 205, and 205
COV (sequence A)If field 56a is present, then field 57a must also
be present.C82 MTs 104 and 107In sequence A, if field 23E is present and
contains RTND, then field 72 must be present. In allother cases
(that is field 23E is not present, or field 23E does not contain
RTND), field 72 is notallowed.Sequence A
If field 23E is … Then field 72 is …
Present and = RTND Mandatory
Present and not = RTND Not allowed
Chapter 3 Alphanumeric Codes
22 July 2011 41
-
Sequence A
If field 23E is … Then field 72 is …
Not present Not allowed
C83 MT 935Either field 23 or field 25, but not both, must be
present in any repetitive sequence.C84 MT 303In sequence A, the presence of field 21 depends on
field 22A as follows:Sequence A
If field 22A is … Then field 21 is …
AMNA Mandatory
AMND Mandatory
CANC Mandatory
DUPL Optional
NEWT Optional
C85 MT 609Field 68B must be present when the immediately
preceding field 23 contains SPOTS orFORWARDS.C86 MT 609Field 68C must be present when the immediately
preceding field 23 contains OPTIONS.C87 Available.
C88 MT 305The currency code in subfield 4 of field 23 must be
the same as the currency code in field 32B.C89 MTs 600, 601, 604, 605, 606, 607, 608, and 609A maximum of 6
decimal digits is permitted in the following: field 32F in MTs 600,
601, 604, 605,606 and 607; fields 60F, 60M, 61, 62F, 62M, 64 and 65
in MT 608; and subfield 6 of fields 68Band 68C in MT 609.MT 620A maximum of 6 decimal digits is permitted in the
subfields «amount» of sequence B: field 32F,index 18, field 32R,
index 19, field 34J, index 21, and of sequence G: field 33J, index
52, andfield 33J, index 54.C90 MTs 700, 710, 720, and 740If field 42a is used, the only
combinations that are allowed are field 42M (on its own) or field
42P(on its own) or both fields 42C and 42(A or D).FIN
42 Error Codes
-
Note:
Note:
C91 MT 608Subfield 4 of field 61 must not be present.
C92 MT 303Sequences B and C are mutually exclusive. Field 94A in
sequence A specifies which type oftransaction is allocated and thus
which one of the two sequences must be present:Sequence Aif field 94A is …
Then sequence B is … Then sequence C is …
FORX Mandatory Not allowed
FXOP Not allowed Mandatory
C93 MT 600Either sequence B or C, but not both, must be
present.C94 MT 104If field 23E in sequence A is present and contains
RFDD, then field 119 of the User Headermust be present and contain
RFDD. If field 23E in sequence A is not present or does not
containRFDD, then field 119 of the User Header must not be
present.Sequence Aif field 23E is …
User Headerthen field 119 is …
Present and = RFDD Mandatory and must contain RFDD
Present and not = RFDD Not allowed
Not present Not allowed
This error code takes precedence over Error codes C75 and
C96.MTs 503, 504, 505, 506, and 507The User Header is mandatory and
must contain a field 119 with a valid code that is identical tothat
contained in subfield 2 of field :22a::COLA//4!c in sequence A.The rule 94 must be applied even if the DSS is present in field
:22F::COLA.C95 MT 303In sequence C, the presence of field 30X depends on
field 23B as follows:Sequence C
If field 23B is … Then field 30X is …
CLAM or PTAM Mandatory
CLEU or PTEU Not allowed
C96 MT 104If field 23E is present in sequence A and contains
RFDD, then:field 21R in sequence A is optional
fields 21E, 50a (option A or K), 52a, 71F and 71G must not be
present in sequence BChapter 3 Alphanumeric Codes
22 July 2011 43
-
Note:
Note:
sequence C must not be present
Otherwise, that is in sequence A, field 23E does not contain
RFDD or field 23E is not present:in sequence A, field 21R must not be present
and in sequence B, the fields 21E, 50a (option A or K), 52a, 71F
and 71G are optionaland sequence C must be present
Sequence A Sequence B
If field 23E is … Then field 21R is … And fields 21E,
50a(option A or K), 52a,71F and 71G are …And sequence C is…
Present and = RFDD Optional Not allowed Not allowed
Present and not =RFDD
Not allowed Optional Mandatory
Not present Not allowed Optional Mandatory
1. See Error codes D75, C94 and D80.
2. Error code C96 takes precedence over Error code D80.
C97 MT 303The presence of sequence D depends on the value of
field 22A in sequence A as follows:Sequence Aif field 22A is …
Then sequence D is …
AMNA, AMND, DUPL or NEWT Mandatory
CANC Optional
MT 504The presence of sequence D is mandatory when in any
occurrence of sequence C,subsequence C1 is present and subsequence
C1a is not present:In sequence(s) C Then sequence D is …
If in one or more occurrence(s) of sequenceC:subsequence C1 is
present andan internal subsequence C1a is not presentMandatory
See Error code D49.MT 505The presence of sequence C is mandatory
when in any occurrence of sequence B,subsequence B1 is present and
subsequence B1a is not present:In sequence(s) B Then sequence C is …
If in one or more occurrence(s) of sequenceB:subsequence B1 is
present andan internal subsequence B1a is not presentMandatory
FIN
44 Error Codes
-
Note:
Note:
Note:
See Error code D49.
C98 MTs 306, 320, 330 , 340, and 620In a sequence, field 15a may
not be the only field, that is if field 15a is present, then at
least oneother field in the sequence must be present.The following lists the sequences per message type:
Message type Sequence
306 I
320, 330 H
340 E
620 H
C99 MT 303In each occurrence of sequence D, the presence of
subsequence D3 depends on field 94A ofsequence A as follows:Sequence Aif field 94A is …
Then subsequence D3 is …
FORX Not allowed
FXOP Mandatory
MT 504Sequence E is mandatory when in any occurrence of sequence
C, subsequence C2 is presentand subsequence C2a is not present.In sequence(s) C Then sequence E is …
If in one or more occurrence(s) of sequenceC:subsequence C2 is
present and an internalsubsequence C2a is not presentMandatory
See Error code D50.MT 505Sequence D is mandatory when in any
occurrence of sequence B, subsequence B2 is presentand subsequence
B2a is not present.In sequence(s) B Then sequence D is …
If in one or more occurrence(s) of sequenceB:subsequence B2 is
present and an internalsubsequence B2a is not presentMandatory
See Error code D50.
Chapter 3 Alphanumeric Codes
22 July 2011 45
-
3.4.2 D Error CodesNote
Similar error codes are used by other SWIFT services, such as
Accord, or Processingfor Euro Banking Association (EBA), and can
have different meanings. The error codesused by each of the
services are described in the respective service documentation.D00 Not used.
D01 MT 303If subfield 1 of field 39P contains CURR, the number
of decimal digits in subfield 3 is checkedagainst the maximum
allowed for the corresponding currency in subfield 2.D02 MTs 304, 360, 361, 362, 364, and 365In sequence A, the
presence of field 21 depends on field 22A as follows:Sequence A
If field 22A is … Then field 21 is …
AMND Mandatory
CANC Mandatory
DUPL Optional
NEWT Optional
MTs 306 and 340In sequence A, the presence of field 21 depends
on field 22A as follows:Sequence A
If field 22A is … Then field 21 is …
AMND Mandatory
CANC Mandatory
NEWT Optional
MT 341In sequence A, the presence of field 21 depends on field
22A as follows:Sequence A
If field 22A is … Then field 21 is …
AMND Mandatory
CANC Mandatory
SETT Optional
FIN
46 Error Codes
-
Note:
Note:
MT 350In sequence A, if field 22A contains ADVC, then field 21
is optional; otherwise field 21 ismandatory:Sequence A
If field 22A is … Then field 21 is …
ADVC Optional
Not = ADVC Mandatory
D03 MT 304In sequence A, the presence of fields 17O and 17N
depend on field 94A as follows:Sequence A
If field 94A is … Then field 17O is … Then field 17N is
…ASET Not allowed Not allowed
AFWD Mandatory Mandatory
See also Error codes D04 and D29.MT 535If field :94a:: is
present in sequence B, then fields :93B::AGGR and :94a::SAFE are
not allowedin any occurrence of subsequence B1b:Sequence Bif field :94a: is …
Then in any occurrence(s) of subsequenceB1b, field :93B::AGGR
and field:94a::SAFE are …
Present Not allowed
Not present Optional
D04 MT 304In sequence A, the presence of field 17F depends on
field 17O as follows:Sequence A
If field 17O is … Then field 17F is …
Y Not allowed
N Mandatory
Not present Not allowed
See also Error codes D03 and D29.MT 535If field :93B::AGGR is
present in subsequence B1b, then :field 94a::SAFE must be present
in thesame subsequence B1b:Sequence B1bif field :93B::AGGR is …
Then in same subsequence B1b,field :94a::SAFE is …
Present Mandatory
Not present Optional
Chapter 3 Alphanumeric Codes
22 July 2011 47
-
D05 MT 535In each occurrence of subsequence B1b, if field
:93B::AVAI or/and :93B::NAVL is/are present,then :field :93B::AGGR
must be present in the same occurrence of subsequence B1b.MTs 700, 705, 707, 710, 720, 740, and 747Either field 39A or
field 39B, but not both, may be present.D06 MTs 700, 705, 707, 710, and 720Either field 44C or 44D but
not both, may be present.D07 Available.
D08 MT 670In subsequence A2, either field :95P::SSIR or field
:94C::SSIR or field :22H::SSIR must bepresent:Subsequence A2if field :95P::SSIR is …
Subsequence A2then field :94C::SSIR is …
Subsequence A2 then field:22H::SSIR is …
Present Not allowed Not allowed
Present Not allowedNot present
Not present Mandatory
D09 MT 670In sequence A, field :95P::SUBM must specify the same
BIC as the Sender in the basic header.If the branch code of the
Sender’s BIC is XXX, then the branch code is not required in
field:95P::SUBM. If the branch code of the Sender’s BIC is not XXX,
then the branch code in field:95P::SUBM must be the same. If the
branch code of :95P:SUBM is present, then the branchcode of the
Sender’s BIC must be the same.In addition, if the Sender’s BIC is a Test and Training BIC then
it’s owning master’s registeredBIC with or without a branch code
could also be specified in field :95P::SUBM Submitting Party.D10 Available.
D11 MT 670In each occurrence of sequence B, if subsequence B1
contains field :95a::INT2 then :95a::INT1must be present in another
subsequence B1:Within each occurrence of sequence Bin subsequence B1
if field :95a::INT1 is …
In the same occurrence of sequence Bthen in another subsequence
B1field :95a::INT2 is …
Present Optional
Not present Not allowed
D12 MT 670In each occurrence of sequence B, in subsequence B1,
field :95P::BENM or :95Q::BENM or:95R::BENM must be present. All
three may be present but once only.FIN
48 Error Codes
-
D13 MTs 380 and 381In sequence C, fields 16R and 16S may not be
the only fields present. If both fields 16R and16S are present,
then at least one of the other fields of the sequence C must be
present.MTs 503, 504, and 506In subsequence B1, fields 16R and 16S may
not be the only fields present. If both fields 16Rand 16S are
present, then at least one other field of the same subsequence must
be present.MT 670In subsequence B2, fields 16R and 16S may not be the only
fields present. If both fields 16Rand 16S are present, then at
least one of the other fields of the same subsequence B2 must
bepresent.In sequence C, fields 16R and 16S may not be the only fields
present. If both fields 16R and16S are present, then at least one
of the other fields of the sequence C must be present.D14 MT 670In subsequence A2, if field :95P::SSIR is not present,
then in subsequence B2 and sequence C,field :22F:PMTH must not be
present. In sequence C, field :22F::PMTH is only allowed
whensubsequence B2, field :22F::PMTH is not present:Subsequence A2if field is …:95P::SSIR
Subsequence B2then field :22F::PMTH is …
Sequence Cthen field :22F::PMTH is …
Present Present Not allowed
Present Not present Optional
Not present Not allowed Not allowed
D15 MT 670In each occurrence of subsequence B1, fields
:95P::ACCW, :95Q::ACCW and :95R::ACCW mayall be present but once
only.In each occurrence of subsequence B1, fields :95P::INT1,
:95Q::INT1 and :95R::INT1 may all bepresent but once only.In each occurrence of subsequence B1, fields :95P::INT2,
:95Q::INT2 and :95R::INT2 may all bepresent but once only.D16 MT 306The presence of subsequence B1 and of sequence C
depends on the values of Type of Event(subfield 1 of field 22K) in
sequence A as follows:Sequence Aif subfield 1 of field 22K is
…
Then subsequence B1is …
And sequence Cis …
CLST Optional Optional
CONF Mandatory Mandatory
KNIN Not allowed Not allowed
KNOT Not allowed Not allowed
OTHR Optional Optional
TRIG Not allowed Not allowed
Chapter 3 Alphanumeric Codes
22 July 2011 49
-
D17 MTs 102 and 102+Field 50a must be present either in sequence
A or in each occurrence of sequence B, but itmust never be present
in both sequences, nor be absent from both sequences.D18 MT 102 (not 102+)If a field 52a, 26T or 77B is present in
sequence A, then that field must not be present in anyoccurrence of
sequence B. When a field 52a, 26T or 77B is present in any
occurrences ofsequence B, that field must not be present in
sequence A.Sequence Aif field 52a is …
In each occurrence ofsequence B
then field 52a is …
Present Not allowed
Not present Optional
Sequence Aif field 26T is …
In each occurrence ofsequence B
then field 26T is …
Present Not allowed
Not present Optional
Sequence Aif field 77B is …
In each occurrence ofsequence B
then field 77B is …
Present Not allowed
Not present Optional
MT 102+If a field 52A, 26T or 77B is present in sequence A, then
that field must not be present in anyoccurrence of sequence B. When
a field 52A, 26T or 77B is in any occurrence of sequence B,that
field must not be present in sequence A.Sequence Aif field 52A is …
In each occurrence ofsequence B
then field 52A is …
Present Not allowed
Not present Optional
Sequence Aif field 26T is …
In each occurrence ofsequence B
then field 26T is …
Present Not allowed
Not present Optional
Sequence Aif field 77B is …
In each occurrence ofsequence B
then field 77B is …
Present Not allowed
FIN
50 Error Codes
-
Note:
Sequence Aif field 77B is …
In each occurrence ofsequence B
then field 77B is …
Not present Optional
D19 MT 102+If in the transaction headers the country codes of
both the Sender’s and Receiver’s BIC arepresent in the list D19_CC
(see note 2), then in each occurrence of sequence B the
followingapply:If field 57A is not present, then the IBAN format (ISO-13616,
see note 1) is mandatory insubfield_1 Account of field 59a in this
occurrence of sequence B.If field 57A is present and the country code of the BIC in 57A
(note) is present in the listD19_CC, then the IBAN format is
mandatory in subfield_1 Account of field 59a in thisoccurrence of
sequence B.In all other cases, the presence of the IBAN format is optional
and its format is not validated insubfield_1 Account of field
59a.1. format special validation.
2. D19_CC list of country codes : AD, AT, BE, BG, BV, CH, CY,
CZ, DE, DK, EE,ES, FI, FR, GB, GF, GI, GP, GR, HU, IE, IS, IT, LI,
LT, LU, LV, MC, MQ, MT,NL, NO, PL, PM, PT, RE, RO, SE, SI, SJ, SK,
SM, TF and VA.In transaction headers, In each occurrence of sequence B,
If country codeof Emitter’s BIC
present inD19_CC
And countrycode of
Receiver’s BICpresent inD19_CC
And field 57Apresent in this
occurrenceof sequence B
And countrycode
of field 57Ais present in
D19_CC
Then in thisoccurrence ofsequence B
in field 59a the
format insubfield_1
Account is …
Yes Yes No NA Mandatory
Yes No No NA Optional
No Yes No NA Optional
No No No NA Optional
Yes Yes Yes Yes Mandatory
Yes No Yes Yes Optional
No Yes Yes Yes Optional
No No Yes Yes Optional
Yes Yes Yes No Optional
Yes No Yes No Optional
No Yes Yes No Optional
No No Yes No Optional
Chapter 3 Alphanumeric Codes
22 July 2011 51
-
Note:
Note:
Note:
This validation rule applies to all types of BICs that are
referenced in field57A: SWIFT BIC, NON-SWIFT BIC, Master, Synonym,
LIVE destination, Test andTraining destination.MT 103+If in the transaction headers the country codes of both
the Sender’s and Receiver’s BIC arepresent in the list D19_CC (see
note 2), then in each occurrence of sequence B the
followingapply:If field 57A is not present, then the IBAN format (ISO-13616,
see note 1) is mandatory insubfield_1 Account of field 59aIf field 57A is present and the country code of the BIC in 57A
(note) is present in the listD19_CC, then the IBAN format is
mandatory in subfield_1 Account of field 59aIn all other cases, the presence of the IBAN format is optional
and its format is not validated insubfield_1 Account of field
59a.1. format special validation.
2. D19_CC list of country codes : AD, AT, BE, BG, BV, CH, CY,
CZ, DE, DK, EE,ES, FI, FR, GB, GF, GI, GP, GR, HU, IE, IS, IT, LI,
LT, LU, LV, MC, MQ, MT,NL, NO, PL, PM, PT, RE, RO, SE, SI, SJ, SK,
SM, TF and VA.In transaction headers,
If country codeof Emitter’s BIC
present inD19_CC
and countrycode of
Receiver’s BICpresent inD19_CC
and field 57Apresent
and countrycode
of field 57Ais present in
D19_CC
then in field 59athe
format insubfield_1
Account is …
Yes Yes No NA Mandatory
Yes No No NA Optional
No Yes No NA Optional
No No No NA Optional
Yes Yes Yes Yes Mandatory
Yes No Yes Yes Optional
No Yes Yes Yes Optional
No No Yes Yes Optional
Yes Yes Yes No Optional
Yes No Yes No Optional
No Yes Yes No Optional
No No Yes No Optional
This validation rule applies to all types of BICs that are
referenced in field57A: SWIFT BIC, NON-SWIFT BIC, Master, Synonym,
LIVE destination, Test andTraining destination.FIN
52 Error Codes
-
Note:
D20 MTs 102 and 102+Field 71A must be present either in sequence
A or in each occurrence of sequence B, but itmust never be present
in both sequences, nor be absent from both sequences.This error code takes precedence over Error codes D50, E13 and
E15.D21 MTs 104 and 107In each occurrence of sequence B, if field
33B is present, then the currency code or the amount,or both, must
be different between fields 33B and 32B.D22 MT 102 and 102+Field 36 (sequence A or sequence B) must be
present in the message if there is any sequenceB which contains a
field 33B with a currency code different from the currency code in
field 32B;in all other cases field 36 is not allowed in the
message.When a field 36 (sequence A or sequence B) is required, EITHER
field 36 must be present insequence A and not in any sequence B, OR
it must be present in every sequence B whichcontains fields 32B and
33B with different currency codes and must not be present in
sequenceA or any other sequence B.In sequence A In sequence B
If field 36 is present Then in minimum one occurrence ofsequence
B field 33B must be present,and currency codes in fields 32B and
33Bmust be different.And field 36 is notallowed in anyoccurrence ofsequence B
In sequence A In each occurrence of sequence B
If field 33B is … And currency codesin fields 32B and
33B are …
Then field 36 is …
Equal Not allowedPresent
Not equal Mandatory
If field 36 is notpresent
Not present NA Not allowed
D23 MT 304The presence of sequence D depends on field 17O as
follows:Sequence Aif field 17O is …
Then sequence D is …
Y Not allowed
N Mandatory
Not present Not allowed
D24 MT 306In sequence A, if field 12F contains VANI, then at
least field 17A or field 17F must contain Y.Both fields may contain
Y.Chapter 3 Alphanumeric Codes
22 July 2011 53
-
Sequence A
If field 12F is … And field 17A is … And field 17F is …
Then thiscombination ofcodes is …
VANI N N Not allowed
VANI N Y Allowed
VANI Y N Allowed
VANI Y Y Allowed
Not = VANI NA NA Allowed
D25 Available.
D26 MT 306In sequence A, the values allowed for field 12E depend
on the value of field 12F as follows:Sequence A
If field 12F is … Then the allowed values for field 12E are
…BINA AMER, EURO
DIGI EURO
NOTO EURO
VANI AMER, BERM, EURO
D27 MT 306In sequence A, the allowed values for subfield 1 of
field 22K depend on fields 12F and 17A asfollows:Sequence A
If field 12F is … And field 17A is … Then the allowed values
forsubfield 1 of field 22K are …VANI N CONF, CLST, OTHR
VANI Y CONF, CLST, KNIN, KNOT,OTHR
Not = VANI N CONF, CLST, TRIG, OTHR
Not = VANI Y CONF, CLST, KNIN, KNOT,TRIG, OTHR
FIN
54 Error Codes
-
Note:
D28 MT 306In sequence A, the presence of fields 30U and 29H
depends on the value of subfield 1 of field22K as follows:Sequence A
If subfield 1 of field 22K is…
Then field 30U is … And field 29H is …
CONF or CLST Not allowed Not allowed
Any other value Mandatory Optional
D29 MT 304The presence of sequence E depends on fields 17F and
17N as follows:Sequence A
If field 17F is … And field 17N is …Then sequence E is
…Y Y Mandatory
Y N Not allowed
Y Not present Not allowed (this case is already
negativelyacknowledged, see Error codes D03 andD04)N Y or N Not allowed
N Not present Not allowed (this case is already
negativelyacknowledged, see Error codes D03 andD04)Not present Y or N Not allowed
Not present Not present Not allowed
See also Error codes D03 and D04.MT 507The presence of sequence
B depends on the value of field :25D::4!c// in sequence Aand the
value of field :13A::Link// in subsequence A2 as follows:Chapter 3 Alphanumeric Codes
22 July 2011 55
-
Note:
Sequence A
If field:25D::4!c/[8c]/4!c Qualifier is
…
And field:25D::REST/[8c]/4!c Data
SourceScheme [8c] is
…
And field:25D::REST/[8c]/
4!c is …
SubsequenceA2
and field:13A::LINK//3!c
is …Then sequence
B is …
:25D::REST//ACCP 503 Optional
:25D::REST//ACCT 503 Optional
:25D::REST//ACCP 504 Mandatory
:25D::REST//ACCT 504 Mandatory
:25D::REST//ACCP 505 Optional
:25D::REST//ACCT 505 Optional
:25D::REST//SUBR NA Optional
Not present
:25D::REST//REJT NA Not allowed
REST
Present NA NA Optional
CPRC NA NA NA Not allowed
IPRC NA NA NA Not allowed
See Error code D52.MT 567If the message is an instruction status
or a cancellation request status (:23G:INST or CAST),AND sequence B
is present, then sequence B should contain a CA option number and
code(:13A::CAON and :22a::CAOP are mandatory).In sequence Aif field :23G:
is …
and sequence B is…
then sequence B,field :13A::CAON is
…
and sequence B,field :22a::CAOP is
…
Present Mandatory MandatoryINST or CAST
Not present NA NA
EVST NA NA NA
D30 MT 306The presence of sequences D and G depends on the value
of field 12F in sequence A asfollows:Sequence Aif field 12F is …
Then sequence D is … And sequence G is …
VANI Mandatory Not allowed
Not = VANI Not allowed Mandatory
FIN
56 Error Codes
-
D31 MT 306If sequence D is present, that is if field 12F in
sequence A contains VANI (see Error code D30),then the presence of
fields 30P and 30Q depends on the value of field 12E in sequence A
asfollows:Sequence A Sequence D
If field 12E is … And field 12E is … Then field 30P is …
And field 30Q is …
Swift T13 – это типичная ошибка, которая может возникнуть в процессе работы с языком программирования Swift. Код ошибки T13 указывает на проблему, связанную с типами данных. Это одна из наиболее распространенных ошибок, с которой сталкиваются разработчики при создании приложений на Swift.
Основная причина возникновения ошибки T13 — неправильное использование типов данных в коде. Ошибка возникает, когда значение переприсваивается переменной с другим типом данных, чем у переменной. Это может привести к конфликту типов данных, что прерывает выполнение программы и генерирует ошибку T13.
Пример:
let number: Int = 5
let message: String = «Hello, world!»
number = message // Ошибка T13 — значение типа String не может быть присвоено переменной типа Int
Чтобы устранить ошибку T13, необходимо внимательно следить за типами данных, которые используются в коде. Убедитесь, что значения, которые вы присваиваете переменным, имеют правильный тип данных. Если вы сталкиваетесь с ошибкой T13, исправьте конфликт типов, изменяя типы данных на соответствующие их значениям.
Содержание
- Код ошибки T13 в Swift: что они значат и как расшифровать
- Частые причины возникновения ошибки T13 в Swift
- Устранение ошибки T13 в Swift: эффективные методы и советы
- Как избежать ошибок T13 в Swift: профилактические меры
- Советы по отладке и исправлению ошибок T13 в Swift
Код ошибки T13 в Swift: что они значат и как расшифровать
Коды ошибок T13 в Swift являются сообщениями об ошибках, которые могут возникать в процессе разработки на языке программирования Swift. Каждый код ошибки имеет свой уникальный идентификатор, который помогает разработчику понять, в чем именно проблема и как ее устранить.
Расшифровка кодов ошибок T13 позволяет быстро определить причину возникновения ошибки и принять соответствующие меры для ее исправления. Чтобы расшифровать код ошибки T13, необходимо обратиться к документации по Swift или использовать инструменты разработки, такие как Xcode.
Ошибки T13 в Swift могут иметь разные причины, связанные с синтаксическими ошибками, проблемами с памятью, некорректными операторами и другими аспектами языка программирования. Расшифровка кодов ошибок T13 помогает разработчику точно определить и исправить причину ошибки, что облегчает и ускоряет процесс разработки.
Когда код ошибки T13 в Swift появляется, наиболее эффективным способом его устранения является использование документации по Swift или поиск по ошибке в Интернете. В документации можно найти описание ошибки и рекомендации по ее исправлению. Также полезно изучить примеры кода, в которых подобная ошибка уже возникала и была успешно исправлена.
Важно помнить, что коды ошибок T13 в Swift являются инструментом для помощи разработчику в процессе разработки. Их расшифровка и исправление ошибок помогают повысить качество кода и улучшить процесс разработки программного обеспечения.
Частые причины возникновения ошибки T13 в Swift
Ошибки T13 в Swift могут возникать по разным причинам, связанным с неправильным использованием операторов, функций и структур языка. Рассмотрим некоторые частые причины возникновения этой ошибки:
- Несовпадение типов данных: Ошибка T13 может возникать, когда происходит попытка присвоения значения одного типа другому типу данных, которые несовместимы. Например, попытка присвоить строковое значение переменной типа Int. В таком случае необходимо проверить и исправить типы данных, чтобы они соответствовали друг другу.
- Отсутствие необходимого значения: Другой причиной ошибки T13 может быть отсутствие значения, которое ожидается в определенном контексте. Например, использование переменной, которая не была инициализирована. В этом случае необходимо проверить, что все переменные и константы были корректно инициализированы перед использованием.
- Ошибки в логике программы: Иногда ошибка T13 может возникать из-за ошибок в логике программы. Например, неправильное условие в операторе if, которое приводит к неправильному выполнению кода. В таком случае необходимо внимательно проверить логику программы и исправить ошибку в условии или операторе.
- Неправильное использование функций и методов: Еще одной причиной ошибки T13 может быть неправильное использование функций и методов языка Swift. Например, передача неправильных аргументов в функцию или вызов метода у несуществующего объекта. В таком случае необходимо проверить, что все аргументы функции передаются в правильном порядке и соответствуют ожидаемым типам данных.
Чтобы избежать ошибки T13 в Swift, рекомендуется тщательно проверять код на соответствие типов данных, правильность инициализации переменных и констант, а также логику программы. При возникновении ошибки необходимо анализировать сообщение об ошибке и проверить соответствующий участок кода на предмет возможных ошибок.
Устранение ошибки T13 в Swift: эффективные методы и советы
Ошибка T13 в языке программирования Swift возникает, когда компилятор обнаруживает попытку присвоить значение оптимального типа одной переменной другой переменной с несовместимым типом данных. Эта ошибка может возникнуть, например, при попытке присвоить значение переменной типа Int переменной типа String.
Чтобы устранить ошибку T13 в Swift, следует выполнить следующие действия:
- Тщательно проверьте код наличия ошибки. Проверьте все строки кода, где происходит присваивание значений переменным.
- Убедитесь, что типы данных переменных совместимы. Проверьте, что тип данных исходной переменной совпадает с типом данных переменной, к которой она присваивается.
- Если типы данных не совместимы, вы можете:
- Изменить тип данных одной из переменных, чтобы сделать его совместимым с другой переменной.
- Добавить преобразование типов данных с помощью оператора as или других операторов Swift, чтобы привести переменную к необходимому типу.
- Проверьте другие строки кода, которые могут вызывать эту ошибку. Иногда ошибка может быть вызвана цепочкой других ошибок или неправильных значений переменных.
- Запустите тесты и проверьте, исправлена ли ошибка T13. Убедитесь, что ваш код работает без ошибок и выдает ожидаемые результаты.
Соблюдение этих методов и советов поможет вам успешно устранить ошибку T13 в языке программирования Swift и продолжить разработку вашего приложения без проблем.
Как избежать ошибок T13 в Swift: профилактические меры
Ошибки T13 в Swift могут быть причиной непредвиденного поведения программы и могут затруднить отладку кода. Чтобы избежать этих ошибок, следует принять несколько профилактических мер:
- Внимательно изучите документацию: перед тем, как приступить к разработке приложения на Swift, рекомендуется тщательно изучить официальную документацию, чтобы понять особенности языка и избежать типичных ошибок.
- Корректно используйте опционалы: опционалы в Swift позволяют обрабатывать значения, которые могут быть nil. Правильное использование опционалов и проверка на nil помогут предотвратить ошибки T13, связанные с неправильным доступом к опциональным значениям.
- Тщательно управляйте жизненным циклом объектов: утечки памяти и неправильное управление жизненным циклом объектов могут привести к ошибкам T13. Рекомендуется аккуратно использовать атрибуты weak и unowned, а также изучить паттерны проектирования, такие как Singleton и Dependency Injection, чтобы правильно управлять объектами.
- Тестирование и отладка: проведение комплексного тестирования и отладки кода помогает выявлять и исправлять ошибки раньше, до того, как они станут причиной ошибок T13. Рекомендуется использовать инструменты для тестирования и отладки, такие как Xcode, чтобы облегчить процесс исправления ошибок.
Вывод: чтобы избежать ошибок T13 в Swift, необходимо более внимательно относиться к процессу разработки, правильно использовать опционалы, управлять жизненным циклом объектов и проводить тестирование и отладку кода. Это позволит улучшить качество программы и предотвратить возникновение ошибок T13.
Советы по отладке и исправлению ошибок T13 в Swift
Ошибка T13 в Swift является ошибкой времени выполнения и может быть вызвана различными причинами, такими как неправильное использование операторов, отсутствие объявления переменной или неправильное приведение типов данных. Вот несколько советов по отладке и исправлению ошибок T13:
- Проверьте правильность написания кода. Одна из самых распространенных причин ошибки T13 — это опечатка или неправильное написание имени переменной или функции. Откройте внимательно свой код и проверьте все имена переменных и функций на наличие ошибок.
- Проверьте правильность использования операторов и приведение типов данных. Ошибка T13 может возникнуть, если вы используете неправильный оператор или приводите типы данных неправильно. Убедитесь, что вы используете правильные операторы и правильно приводите типы данных в своем коде.
- Используйте отладку. Отладка — это процесс поиска и исправления ошибок в коде. В Swift вы можете использовать отладчик Xcode, чтобы отслеживать значение переменных и шагать по коду по одной строке. Используйте отладчик, чтобы поймать ошибку T13 и увидеть, какие значения переменных вызывают проблему.
- Используйте команду «print». Если вы не можете использовать отладчик, чтобы отслеживать значение переменных, вы можете использовать команду «print» в своем коде, чтобы выводить значения переменных в консоль. Например, вы можете написать «print(myVariable)» чтобы увидеть значение переменной myVariable в консоли.
- Изучите документацию. Если вы столкнулись с ошибкой T13, которую не можете исправить, обратитесь к официальной документации по Swift, чтобы узнать больше о возможных причинах ошибки и способах ее исправления. Документация может помочь вам понять, как правильно использовать операторы и функции в Swift и предоставить примеры кода для исправления ошибки.
Важно помнить, что код T13 может иметь различные причины и способы исправления в зависимости от контекста. При отладке ошибок T13 в Swift важно быть терпеливым и систематичным, а также использовать доступные инструменты, такие как отладчик и команду «print». Надеюсь, эти советы помогут вам отладить и исправить ошибки T13 в своем коде на Swift!