Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use fullScreenCover with iOS 14 but sheet for 13

Tags:

ios

swiftui

Imagine you've built a screen that utilizes the sheet API to present modal sheets, and now with SwiftUI 2.0 you want to use fullScreenCover instead when run on iOS 14. How do you do so? Xcode offers suggestions:

  • Add if #available version check
  • Add @available attribute

If you use the #available version check, it wraps all of that scoped code with #available, so you'd have to duplicate all of that to change that one line of code. If you use @available you have to duplicate the entire struct.

Is there a way to have "in-line" logic that says if iOS 14 add this modifier, otherwise fall back to this one, without having to duplicate all of the rest of the view code?

An example:

VStack {
    //a lot of other views here
}
.sheet(isPresented: self.$showingSomeView) { //TODO: Replace sheet with fullScreenCover for iOS 14+
    SomeView()
}
like image 300
Jordan H Avatar asked Jul 23 '20 14:07

Jordan H


People also ask

How do I view full screen in SwiftUI?

How to present a full screen modal view using fullScreenCover() SwiftUI's fullScreenCover() modifier gives us a presentation style for times when you want to cover as much of the screen as possible, and in code it works almost identically to regular sheets.

How do I use sheets in SwiftUI?

To use a sheet, give it something to show (some text, an image, a custom view, etc), add a Boolean that defines whether the detail view should be showing, then attach it to your main view as a modal sheet. Important: If you're targeting iOS 14 or below, you should use @Environment(\.

How do I present a view in Modally SwiftUI?

Modal views in SwiftUI are presented using the sheet modifier on a view or control. The simplest way is to have @State property to indicate when it should be visible. To hide the modal view, we can use the environment parameter or pass a binding to the modal view object.

How do I dismiss a sheet in SwiftUI?

The first option is to tell the view to dismiss itself using its presentation mode environment key. Any view can read its presentation mode using @Environment(\. presentationMode) , and calling wrappedValue. dismiss() on that will cause the view to be dismissed.


1 Answers

Here is possible approach

struct DemoCompatibleFullScreen: View {
    @State private var activateFullScreen = false
    var body: some View {
        Button("Toggle") { self.activateFullScreen.toggle() }
            .compatibleFullScreen(isPresented: $activateFullScreen) {
                Text("I'm in Full Screen!")
            }
    }
}

extension View {
    func compatibleFullScreen<Content: View>(isPresented: Binding<Bool>, @ViewBuilder content: @escaping () -> Content) -> some View {
        self.modifier(FullScreenModifier(isPresented: isPresented, builder: content))
    }
}

struct FullScreenModifier<V: View>: ViewModifier {
    let isPresented: Binding<Bool>
    let builder: () -> V

    @ViewBuilder
    func body(content: Content) -> some View {
        if #available(iOS 14.0, *) {
            content.fullScreenCover(isPresented: isPresented, content: builder)
        } else {
            content.sheet(isPresented: isPresented, content: builder)
        }
    }
}
like image 77
Asperi Avatar answered Oct 19 '22 20:10

Asperi