FullScreenCover in SwiftUI

DevTechie Inc
May 11, 2023

FullScreenCover presents a modal view that covers as much of the screen as possible. Modal is presented when binding to a boolean value is true or toggles true.

fullScreenCover modifier takes a few parameters.

isPresented: is the variable used to trigger the modal presentation. Upon dismissal, isPresented automatically sets back to false.

onDismiss: this is a closure, which is called when the modal is dismissed.

content: content is a ViewBuilder closure that returns a view with the modal content.

Lets put an example together. We will need a State variable to launch the fullScreenCoverButton to toggle the state and fullScreenCover modifier itself. We also need the view we would like to show so we will create a simple view which can be dismissed upon tapping anywhere on the screen.

struct DevTechieFullScreenCoverExample: View {
    
    @State private var showFullScreenCover = false
    
    var body: some View {
        NavigationStack {
            VStack(alignment: .leading) {
                Text("Show me the fullScreenCover")
                    .font(.title3)
                Button("OK") {
                    showFullScreenCover.toggle()
                    
                }
                .fullScreenCover(isPresented: $showFullScreenCover) {
                    FullScreenViewExample()
                }
                Spacer()
            }
            .padding()
            .frame(maxWidth: .infinity, alignment: .leading)
            .navigationTitle("DevTechie")
        }
    }
}struct FullScreenViewExample: View {
    @Environment(\.dismiss) var dismiss
    var body: some View {
        ZStack {
            Color.orange.opacity(0.2)
                .ignoresSafeArea()
            VStack {
                Text("This is a FullScreenModal")
                Text("Tap anywhere to dismiss")
            }
            .font(.title)
        }
        .onTapGesture {
            dismiss()
        }
    }
}

We can perform some action when the modal is dismissed by either calling a function in onDismiss or defining closure for onDismiss. Let’s use onDismiss in our example.

struct DevTechieFullScreenCoverExample: View {
    
    @State private var showFullScreenCover = false
    
    @State private var backColor = Color.white
    
    var body: some View {
        NavigationStack {
            ZStack {
                backColor
                    .ignoresSafeArea()
                
                VStack(alignment: .leading) {
                    Text("Show me the fullScreenCover")
                        .font(.title3)
                    Button("OK") {
                        showFullScreenCover.toggle()
                        
                    }
                    .fullScreenCover(isPresented: $showFullScreenCover, onDismiss: onDismiss) {
                        FullScreenViewExample()
                    }
                    Spacer()
                }
                .padding()
                .frame(maxWidth: .infinity, alignment: .leading)
            }
            .navigationTitle("DevTechie")
        }
    }
    
    func onDismiss() {
        backColor = Color.mint.opacity(0.4)
    }
}

Another overload of fullScreenCover modifier takes item as a parameter instead of isPresented parameter. Item is a value provided to build the modal, which will be presented, when value goes from nil to a valueItemneeds to conform to the identifiable protocol and upon dismissal of modal, item automatically becomes nil.

Let’s create an item model first:

struct MessageItem: Identifiable {
    let id = UUID()
    let message: String
}

We will add this to our views.

Main view:

struct DevTechieFullScreenCoverExample: View {
    
    @State private var message: MessageItem? = nil
    
    var body: some View {
        NavigationStack {
            VStack(alignment: .leading) {
                Text("Show me the fullScreenCover")
                    .font(.title3)
                Group {
                    Button("iOS") {
                        message = .init(message: "Message is: learn iOS from DevTechie")
                    }
                    
                    Button("Visit") {
                        message = .init(message: "Visit DevTechie.com")
                    }
                }
                .fullScreenCover(item: $message) { msg in
                    FullScreenViewExample(messageItem: msg)
                }
                Spacer()
            }
            .padding()
            .frame(maxWidth: .infinity, alignment: .leading)
            .navigationTitle("DevTechie")
        }
    }
    
}

FullScreenViewExample view

struct FullScreenViewExample: View {
    @Environment(\.dismiss) var dismiss
    let messageItem: MessageItem
    
    var body: some View {
        ZStack {
            Color.orange.opacity(0.2)
                .ignoresSafeArea()
            VStack {
                Text(messageItem.message)
            }
            .font(.title)
        }
        .onTapGesture {
            dismiss()
        }
    }
}