Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI: Error while using if #available while trying to build to iOS 13 and iOS 14 in Xcode 12 beta 2

Tags:

xcode

swift

ios13

So I'm trying to make it so that my app can deploy on iOS 13 (technically I'm wanting iOS 13.5) as well as iOS 14 so I've written these lines of code to test it:

struct ContentView: View {
    var body: some View {
        if #available(iOS 14.0, *) {
            List {
                Text("Cool!")
                Text("Cool!")
                Text("Cool!")
                Text("Cool!")
            }
            .listStyle(InsetGroupedListStyle())
            
        } else {
            List {
                Text("Cool!")
                Text("Cool!")
                Text("Cool!")
                Text("Cool!")
            }
            .listStyle(GroupedListStyle())
            .environment(\.horizontalSizeClass, .regular)
        }
    }
}

Building to iOS 14 works great, however, whenever I build to iOS 13.5 on a physical phone and the simulator, I get this error in the AppDelegate:

Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)

I've made sure to set my iOS Deployment Target to iOS 13.5 and I'm using Xcode 12 beta 2. I have tried using beta 1 with the same result (though I used the same file, so potentially that's why?). I'm not sure if I'm doing anything wrong or if this is a bug. When using the code for iOS 13.5 alone (without the if #available) it works as expected, but only when I add that checker is when my problems arise. Any help would be appreciated!

like image 980
Jabinator1 Avatar asked Jul 10 '20 16:07

Jabinator1


2 Answers

Unfortunately i can reproduce this bug in Xcode 12 beta 4, so here a workaround. You can wrap iOS 14 code into AnyView and all will compile successfully. In this particular case you can use the ViewModifier to make code look more swifty.

struct ContentView: View {
    var body: some View {
        List {
            Text("Cool!")
            Text("Cool!")
        }
        .modifier(GroupedListModifier())
    }
}

struct GroupedListModifier: ViewModifier {
    func body(content: Content) -> some View {
        Group {
            if #available(iOS 14, *) {
                AnyView(
                    content
                        .listStyle(InsetGroupedListStyle())
                )
            } else {
                content
                    .listStyle(GroupedListStyle())
                    .environment(\.horizontalSizeClass, .regular)
            }
        }
    }
}
like image 197
pacification Avatar answered Sep 24 '22 20:09

pacification


This bug should be fixed in Xcode 12 beta 5 and later. If it's not, please use Feedback Assistant to report the issue.

For anyone who's curious, the problem was that, even though the iOS 14 branch wasn't taken on iOS 13 devices, the types of the views that would have been produced by that branch were still being processed by SwiftUI, and some of those types didn't exist in iOS 13. The AnyView workaround suggested by @pacification works because it hides the type information in the iOS 14 branch so that SwiftUI doesn't process it unless that branch is taken. And in fact, Xcode 12 beta 5 basically fixes this bug by automatically wrapping the if #available branch in AnyView.

like image 33
Becca Royal-Gordon Avatar answered Sep 23 '22 20:09

Becca Royal-Gordon