ModalPresentationView
Takes the boilerplate out of managing modal presentations in SwiftUI.
Background
SwiftUI currently provides two different ways to manage modal presentations:
-
The simplest,
PresentationButton
, accepts aDestination
parameter and presents it over the current context. It doesn't provide a control for manual dismissal, instead appearing to rely on the interactive dismissal gesture that's part of the new default.pageSheet
modal presentation style. -
Alternatively, the more powerful
presentation(_:)
modifier allows you to take control of the presentation state yourself, by accepting an optional parameter of typeModal
.
ModalPresentationView
sits in the middle, providing a
ModalPresentationButton
control with the same API as PresentationButton
,
but additionally:
-
Unlike the
presentation(_:)
modifier, automatically manages the state of the modal via a newModalNavigationView
. If you're familiar withNavigationView
, then you already know how to use it. -
Provides for manual dismissal via
ModalDismissButton
, in addition to the existing interactive dismiss gesture.
Demo
Example code
import ModalPresentationView
import SwiftUI
struct App: View {
var body: some View {
ModalPresentationView {
ModalPresentationButton(destination: DetailScreen()) {
Text("Present")
}
}
}
}
struct DetailScreen: View {
var body: some View {
ModalDismissButton {
Text("Dismiss")
}
}
}
Installation
- In Xcode, open your project and navigate to File > Swift Packages > Add Package Dependency...
- Paste the repository URL and follow the prompts to add the library to your project.
How does it work?
Internally, ModalPresentationView
defines two custom environment keys, which
it then uses to communicate between the container and the buttons, regardless
of where they're placed in your view hierarchy.
-
Firstly,
ModalPresentationView
injects apresent(_:)
closure into the environment using the.modalPresentAction
key. -
When tapped,
ModalPresentationButton
reads the closure from the environment and calls it to notifyModalPresentationView
to trigger a presentation. The presentation button passes the destination view into the closure by first wrapping it in anAnyView
. -
ModalPresentationView
updates its internal state to pass the destination view into thepresentation(_:)
view modifier. It also sets adismiss()
closure on the environment of the presented view using the.modalDismissAction
environment key. -
Finally,
ModalDismissButton
reads thedismiss()
closure from the environment and calls it when tapped, causingModalPresentationView
to update its internal state again and remove the presented modal.
Contributing
See the CONTRIBUTING document for details about how you can contribute.
License
ModalPresentationView is Copyright (c) 2019 thoughtbot, inc. It contains free software that may be redistributed under the terms specified in the LICENSE file.
About
ModalPresentationView is maintained by Adam Sharp and funded by thoughtbot, inc. The names and logos for thoughtbot are trademarks of thoughtbot, inc.
We love open source software! See our other projects or hire us to help build your product.