Not sure if this is a SwiftUI bug or a Swift bug so I'm posting this also into the Swift forum.
I've encountered an issue where storing a throws(PermissionError) closure as a property inside a SwiftUI View causes a runtime crash with EXC_BAD_ACCESS on iOS 17, while it works correctly on iOS 18.
Here’s an example of the affected code:
enum PermissionError: Error {
case denied
}
struct PermissionCheckedView<AllowedContent: View, DeniedContent: View>: View {
var protectedView: () throws(PermissionError) -> AllowedContent
var deniedView: (PermissionError) -> DeniedContent
init(
@ViewBuilder protectedView: @escaping () throws(PermissionError) -> AllowedContent,
@ViewBuilder deniedView: @escaping (PermissionError) -> DeniedContent
) {
self.protectedView = protectedView
self.deniedView = deniedView
}
public var body: some View {
switch Result(catching: protectedView) {
case .success(let content): content
case .failure(let error): deniedView(error)
}
}
}
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
PermissionCheckedView {
} deniedView: { _ in
}
}
}
}
Here's the stack trace (not sure how to get the txt version so posting image).
Since I noticed some func like swift_getTypeByMangledNameInContextImpl in the stack trace I thought that this could be a Swift bug
Typed throws is new in the Swift 6 compiler and iOS 18, so I'm guessing the demangling used by SwiftUI on iOS 17 doesn't know how to handle it. I think typed throws is back deployable, but only if you don't rely on implementation details like SwiftUI. I'm not sure if the language can fix this, but hopefully there's something Apple can do.
In general I can use typed throws on iOS 17 as long as I don't store closures in views. I suppose there's nothing we can do if Apple doesn't tackle this
SwiftUI (am grouping SwiftUI, SwiftUICore and AttributeGraph together here) relies heavily on runtime reflection internally.
My guess is that SwiftUI's internal runtime reflection code was written relative to the Swift runtime ABI interface before typed throws was implemented. Typed throws the language feature backdeploys, yes, and implementation is (I could be wrong) purely additive from what I understand.
That being said, if you write code that relies on an exhaustive understanding of all possible runtime structures (I imagine SwiftUI's internals do this), you're bound to either make assumptions or implement code-paths that exit-early with respect to new, 'foreign' metadata.
I'm guessing that somewhere in the implementation there are areas that trip up on the runtime changes (even if they're purely additive in the technical sense) introduced with the implementation of typed throws as a new language feature.