Swift Errors

Swift Errors

Understand how to prevent and handle errors in Swift.

Here's an explanation of syntax errors, runtime errors and error handling in Swift:

Syntax Errors:

  • These are errors that occur when the code does not follow the rules of the programming language.

  • The code will not compile due to syntax errors.

  • Examples: missing a semicolon, using incorrect brackets, misspelling a keyword etc.

Runtime Errors:

  • These errors occur when the code is running/executing.

  • The code compiles fine but crashes at runtime due to an error.

  • Examples: accessing an array out of bounds, dividing by zero, force unwrapping an optional that is nil etc.


Error Handling:

  1. Define custom error types using enums:
enum VendingMachineError: Error {
    case invalidSelection 
    case insufficientFunds(coinsNeeded: Int)
    case outOfStock 
}
  1. Throw errors from functions using throw:
func makeSelection(selection: Int) throws {
    ...
    if selection < 1 || selection > 9 {
        throw VendingMachineError.invalidSelection
    }
    ...
}
  1. Catch errors using do - catch:
do {
    try makeSelection(selection: 5) 
} catch VendingMachineError.invalidSelection {
    print("Invalid selection.")
} catch {
    print("Unexpected error: \(error)")
}
  1. Use a catch-all case to catch any unexpected errors.

The strategy is to define meaningful, custom error types for expected errors and have a catch-all case to handle any unexpected runtime errors.


Proactive Programming

Preventing errors from happening in the first place is better than reacting to errors after they occur. Here are some ways to use proactive coding to prevent errors:

  1. Use assertions: Assertions allow you to verify assumptions about your code, and crash if the assertion fails. This helps catch bugs earlier. For example:
assert(name.count > 2, "Name should be at least 3 characters long")

If name has less than 3 characters, the assertion will fail and crash the program, alerting you to fix the input validation earlier.

  1. Validate input before using it: Instead of force unwrapping optionals or accessing arrays out of bounds, validate any user input before using it. For example:
guard name.count > 2 else {
    // Show error
    return 
}
  1. Define preconditions and postconditions: These are similar to assertions, but used to define the valid state of a function before and after it executes. For example:
precondition(age > 0, "Age must be greater than 0")

// Function code

postcondition(result != nil, "Result should not be nil")
  1. Use protocol extensions to define default behavior: This reduces the chance of implementing a method incorrectly.

So in summary, using assertions, input validation, pre/post-conditions and protocol extensions can help prevent many errors from happening in the first place. Try/catch is still useful for unexpected runtime errors, but the proactive techniques allow you to catch bugs earlier and write more robust code.


Disclaim: I'm learning Swift using AI. These are my notes. I ask questions so you don't have to. If you have comments, do not hesitate to post. I like some feedback.