When SwiftUI was introduced back in 2019, it came with a fantastic new development tool in the form of Xcode Previews. In 2023, preview support was added for UIKit and AppKit views, and since then Apple has gone on to improve the previewing experience with tools like the #Preview macro, and the @Previewable annotation. However, for as long as this feature has existed, developers have been plagued by one constant source of blockers - preview crashes. Today we will look at how to resolve these so you can get back to developing your UI quickly and easily with Xcode previews.
We've all been there. You're right in the middle of developing a complex layout or animation in your UI, and then Xcode hits you with this little nugget of joy:
Oh dear. For many, this is the end of their UI previewing journey. This problem can persist for weeks until it decides to resolve itself, only to break again a short time later. But what to do?
Nine times out of ten, the fix for this is surprsingly simple. The previewing engine runs inside an iOS simulator in order to produce the previews that are displayed inside Xcode. Simply resetting this simulator will usually get you back up and running. To do this, run the following command:
xcrun simctl --set previews delete all
This clears the cache used by the previews simulator. Xcode will now start generating previews using a fresh simulator, without the cached state that was causing crashes previously.
Some crashes will continue even after clearing the previews simulator cache. In these scenarios, navigate to Xcode's menu bar and toggle on Editor > Canvas > Legacy Preview Execution. This will slow down the generation of previews, but should get them working again.
Occasionally you may come across a different kind of error. Not a crash, but something else that prevents your previews from displaying. This is an error stating "Failed to launch app in a reasonable time". Because your previews run in a simulator, your entire app needs to be installed and run in the simulator in order for previews to be generated. Upon app launch you are likely initialising analytics tracking, crash reporting, remote logging etc. These can all increase app startup time and lead directly to this error in the preview canvas. Fortunately we can modify our app's behaviour when it is being run for the purpose of generating previews by checking the application's ProcessInfo:
import Foundation
extension ProcessInfo {
var isRunningForPreviews: Bool {
environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1"
}
}
We can then use this property to disable processor intensive tasks when the app is being run to generate previews:
if !ProcessInfo.processInfo.isRunningForPreviews {
/// Perform processor intensive tasks
}