Addressing crashes from Swift runtime errors
Identify the signs of a Swift runtime error, and address the crashes runtime errors cause.
Overview
Swift uses memory safety techniques to catch programming mistakes early. Optionals require you to think about how best to handle a nil value. Type safety prevents casting an object to a type that doesn’t match the object’s actual type.
If you use the ! operator to force unwrap an optional value that’s nil, or if you force a type downcast that fails with the as! operator, the Swift runtime catches these errors and intentionally crashes the app. If you can reproduce the runtime error, Xcode logs information about the issue to the console. On ARM processors, the exception info in the crash report looks like:
Exception Type: EXC_BREAKPOINT (SIGTRAP)
...
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5On Intel processors (including apps for macOS, Mac Catalyst, and the simulators for iOS, iPadOS, tvOS, and watchOS), the exception info in the crash report looks like:
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
...
Exception Note: EXC_CORPSE_NOTIFY
Termination Signal: Illegal instruction: 4
Termination Reason: Namespace SIGNAL, Code 0x4Identify the location of the error
The crash report shows the thread that encountered the runtime error, with a frame in the backtrace identifying the specific line of code.
Thread 0 Crashed:
0 MyCoolApp 0x0000000100a71a88 @objc ViewController.viewDidLoad() (in MyCoolApp) (ViewController.swift:18)
1 MyCoolApp 0x0000000100a71a40 @objc ViewController.viewDidLoad() (in MyCoolApp) (ViewController.swift:18)
2 UIKitCore 0x00000001c569e920 -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 100
3 UIKitCore 0x00000001c56a3430 -[UIViewController loadViewIfRequired] + 936
4 UIKitCore 0x00000001c56a3838 -[UIViewController view] + 28In this example, thread 0 encountered the error. Frame 0 of this thread shows that the runtime error occurs on line 18 of ViewController.swift, in the viewDidLoad method:
0 MyCoolApp 0x0000000100a71a88 @objc ViewController.viewDidLoad() (in MyCoolApp) (ViewController.swift:18)Change your code
Look at the other frames in the backtrace to identify the exact function calls that produced the error, and determine whether you used a force unwrap or a forced downcast. A force unwrap uses the ! operator. For example:
let image = UIImage(named: "aMissingIcon")!
print("Image size: \(image.size)")Instead of the force unwrap, gracefully handle the nil value where it first appears in your code by using optional binding:
if let image = UIImage(named: "aMissingIcon") {
print("Image size: \(image.size)")
}See the Swift documentation for more information on Optionals.
For type casts, a forced downcast uses the as! operator. This example crashes if library contains something other than a Song type:
for item in library {
let song = item as! Song
print("Song: \(song.name), by \(song.artist)")
}Instead of the forced downcast, gracefully handle the scenarios where the type of the object doesn’t match the expected type by using a conditional downcast:
for item in library {
if let song = item as? Song {
print("Song: \(song.name), by \(song.artist)")
}
}See the Swift documentation for more information on Type Casting.