backgroundTask modifier crashing Swift compiler

10 October 2022

As of Xcode 14.0, adding a backgroundTask modifier to anything more than a single view will likely cause a not super-helpful compiler error.

Say you have something like this:

@main
struct WeatherApp: App {
    @StateObject var weatherData = WeatherDataStore()
    
    var body: some Scene {
        WindowGroup {
            SimpleWeatherView()
                .environmentObject(weatherData)
        }
        .backgroundTask(.appRefresh("WeatherCheck")) {
            await updateWeatherData()
        }
    }
}

Xcode will not be happy, letting you know that Command CompileSwift failed with a nonzero exit code. Not exactly the most helpful, though digging in to the build output yields this gem:

$@_opaqueReturnTypeOf("$s7SwiftUI5ScenePAAE14backgroundTask_6actionQrAA010BackgroundE0Vyqd__qd_0_G_qd_0_qd__YaYbcts8SendableRd__sAIRd_0_r0_lF", 0) __>>>, (), ()> // user: %38
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the project and the crash backtrace.

Turns out that for now you will need to encapsulate the view and its modifiers into a single view like this:

@main
struct WeatherApp: App {
    var body: some Scene {
        WindowGroup {
	    TemporaryWrapperView()
        }
        .backgroundTask(.appRefresh("WeatherCheck")) {
            await updateWeatherData()
        }
    }
}

struct TemporaryWrapperView: View {
    @StateObject var weatherData = WeatherDataStore()
    
    var body: some View {
        SimpleWeatherView()
            .environmentObject(weatherData)
    }
}

For more details check out this thread on the Apple Developer forums. As stated there, if all is well this workaround should hopefully not be needed once Xcode 14.1 ships.