SwiftUI is still very new and still in beta but it is already great and we can play with it! While writing my first SwiftUI app I needed to present a modal sheet. Let's look at how it's done.

First let's create our main view. It is just a simple view with a button and a modifier.

struct ContentView: View {
    @State var modalDisplayed = false
    
    var body: some View {
        Button(action: { self.modalDisplayed = true }) {
            Text("Show Modal")
        }.sheet(isPresented: $modalDisplayed) {
            DetailView(onDismiss: {
                self.modalDisplayed = false
            })
        }
    }
}

SwiftUI is declarative and the typical presentation we're used to from UIKit just does not exist. Instead we need to define the UI with its possible states in mind.

To even begin we need to define our modalDisplayed variable annotated with @State property wrapper. This lets SwiftUI know that our UI can depend on the value of this property. When the property changes, the UI is automatically updated.

We then create our button (which is basically our UI) and call a sheet modifier on it. This modifier lets us present a sheet based on the value of the modalDisplayed variable we defined above. Notice the dollar sign in $modalDisplayed. This creates a binding that ties our UI to this variable's value through its property wrapper.

The sheet modifier also takes an optional onDismiss parameter - a closure that is executed when the sheet is dismissed by dragging down on it. We do not need that though as the modalDisplayed value is changed for us automatically by SwiftUI.

The last parameter is a builder of the view we want to present. In our case this is simply a DetailView instance. Our view takes an onDismiss parameter - a closure that is to be executed when we want to dismiss the view programatically. In SwiftUI there is no way of simply calling a function to dismiss the currently presented view and so this closure is needed. When executed it simply sets the modalDisplayed variable to false which - since it is bound to our UI - makes SwiftUI dismiss the presented view.

The code of DetailView is very simple. It is just a view with a button. The button executes the closure passed to it to dismiss its currently presented parent view.

struct DetailView: View {
    var onDismiss: () -> ()
    
    var body: some View {
        Button(action: { self.onDismiss() }) {
            Text("Dismiss")
        }
    }
}

Let's look at the full code...

import SwiftUI

struct DetailView: View {
    var onDismiss: () -> ()
    
    var body: some View {
        Button(action: { self.onDismiss() }) {
            Text("Dismiss")
        }
    }
}

struct ContentView: View {
    @State var modalDisplayed = false
    
    var body: some View {
        Button(action: { self.modalDisplayed = true }) {
            Text("Show Modal")
        }.sheet(isPresented: $modalDisplayed) {
            DetailView(onDismiss: {
                self.modalDisplayed = false
            })
        }
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

That's basically it! With just a couple of lines we can present and dismiss a sheet with our custom view.