Fixing and Avoiding Crashes in Swift Code
When you start out developing iOS or Mac apps in Swift, you run into a common problem. Your project builds without any errors but crashes when you run it. It’s frustrating to have your code not work, and the cryptic messages Xcode spews don’t help much.
In this article you’ll learn how to get Xcode to show you where the crash occurs in your code. You’ll also learn the most common causes of crashes in Swift apps and how to avoid them.
Add an Exception Breakpoint to Locate the Crash
Adding an exception breakpoint in Xcode makes it easy to find where your code crashes. Open Xcode’s breakpoint navigator by choosing View > Navigators > Show Breakpoint Navigator.
Click the Add (+) button at the bottom of the breakpoint navigator and choose Exception Breakpoint. A popover opens for the breakpoint.
Make sure the Exception menu is set to break on all exceptions and to break when an exception is thrown.
Now when your app crashes, Xcode breaks into the debugger and shows you the line of code where the crash occurred. Showing the line of code where the crash occurred comes in handy when you’re trying to figure why your app crashed.
If you look at the screenshot of the breakpoint navigator, you will notice the exception breakpoint is in the User section. User breakpoints apply to all projects so you don’t have to set them for each project.
Because exception breakpoints help so much to find where your apps crash, they’re strong candidates to be user breakpoints. To make a breakpoint a user breakpoint, select it in the breakpoint navigator, control-click, and choose Move Breakpoint To > User. Now the exception breakpoint will fire when any of your projects crash.
Common Crash Causes
Now that you can determine where your app crashes, you want to know why your code is crashing and how to fix it. Without seeing your code, I can’t tell you exactly why your code is crashing, but I can tell you the most common causes of crashes.
- Unwrapping a nil Swift optional
- Disconnected outlets
- Accessing an element outside an array’s bounds
- Accessing an uninitialized variable
Unwrapping a Nil Optional
The leading cause of crashes in Swift apps is unwrapping a nil optional value. When you unwrap a nil optional value, you will see the following error message in Xcode’s debug console:
Fatal error: Unexpectedly found nil while unwrapping an Optional value
This error is usually caused by two things. First, force unwrapping an optional by adding an exclamation point to a variable’s name. Second, using as!
to downcast an optional value to a specific type.
The fix is to avoid force unwrapping. Use if let
or guard
statements to safely unwrap your optionals. Use as?
instead of as!
when downcasting. The following articles provide more detailed information on optionals:
Disconnected Outlets
The second most common cause of crashes in Swift apps is having a disconnected outlet for a user interface element and accessing that outlet in your code.
You can check if an outlet is connected in Xcode’s source code editor. Next to an outlet is a circle. The following screenshot shows a disconnected outlet:
A connected outlet has the circle filled in.
To connect the outlet open Xcode’s assistant editor so the storyboard and the source code file are both open. Select the user interface element in the storyboard. Hold down the Control key and drag to the outlet in the source code file.
Out of Range Array Access
If you try to access an element in an array that is not in the array’s range, your app will crash. Out of range errors are usually off-by–1 errors because array indices start at 0 instead of 1. An array with 10 elements has indices 0–9, not 1–10. If you try to access the tenth element with the following code:
myArray[10]
The app will crash with an out of range error because the subscript [10]
references the 11th member of an array with only 10 elements.
You can also get an out of range error if you try to access elements in an empty array. An empty array has no elements so any subscript is out of range. Swift arrays have an isEmpty
property you can check to see if the array is empty.
Accessing an Uninitialized Variable
This error usually occurs in view controllers when you try to access a property in viewDidLoad
or similar initialization function. viewDidLoad
is called before the code that initializes the property, causing a crash.
A common fix for accessing a property before it’s initialized is to access the property in viewDidAppear
, which gets called after viewDidLoad
.