I have same issue with Xcode 13.2 (13C90), SwiftUI and #available in if statement. Project works fine with old Xcode and in Debug configuration, but crashes with old versions of iOS (iOS 13 & 14) in Release configuration (or using TestFlight).
Steps to reproduce:
Create a new SwiftUI iPhone Application project.
Set the iOS target to 14
Create a simple view with an if #available statement and any new iOS 15 modifier. For example:
struct ContentView: View {
var body: some View {
if #available(iOS 15.0, *) {
List {
Text("iOS 15 new feature")
.listRowSeparator(.hidden)
}
} else {
List { Text("Old style") }
}
}
}
Change the build configuration in the launch scheme to Release and run the app on a device or simulator with iOS 14.
Application will crash with error:
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
* frame #0: 0x00007fff2f38f127 libswiftCore.dylib`swift::ResolveAsSymbolicReference::operator()(swift::Demangle::__runtime::SymbolicReferenceKind, swift::Demangle::__runtime::Directness, int, void const*) + 55
frame #1: 0x00007fff2f3b15dd libswiftCore.dylib`swift::Demangle::__runtime::Demangler::demangleSymbolicReference(unsigned char) + 141
frame #2: 0x00007fff2f3ae5a8 libswiftCore.dylib`swift::Demangle::__runtime::Demangler::demangleType(__swift::__runtime::llvm::StringRef, std::__1::function<swift::Demangle::__runtime::Node* (swift::Demangle::__runtime::SymbolicReferenceKind, swift::Demangle::__runtime::Directness, int, void const*)>) + 168
frame #3: 0x00007fff2f394974 libswiftCore.dylib`swift_getTypeByMangledNameImpl(swift::MetadataRequest, __swift::__runtime::llvm::StringRef, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 516
frame #4: 0x00007fff2f39212d libswiftCore.dylib`swift::swift_getTypeByMangledName(swift::MetadataRequest, __swift::__runtime::llvm::StringRef, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 477
frame #5: 0x00007fff2f39235b libswiftCore.dylib`swift_getTypeByMangledNameInContext + 171
frame #6: 0x000000010305add7 AvailableBug`__swift_instantiateConcreteTypeFromMangledName at <compiler-generated>:0
...
It looks like SwiftUI is trying to initialize the content of the if statement and crashes on an unknown modifier or element.
If creates a simple wrapper structure that defers initialization to the "body", everything works fine.
Workaround:
struct LazyContent<Content: View>: View {
let content: ()->Content
init (@ViewBuilder content: @escaping ()->Content) {
self.content = content
}
var body: some View {
content()
}
}
struct ContentView: View {
var body: some View {
if #available(iOS 15.0, *) {
LazyContent {
List {
Text("iOS 15 new feature")
.listRowSeparator(.hidden)
}
}
} else {
List { Text("Old style") }
}
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Tags: