I've a main view that displays a modal sheet. As I've multiple modals, I use enum and State to control which sheet is presented.
@State var activeSheet: Sheet?
Inside my MainView:
Button(action: {
activeSheet = .settings
}, label: {
Text(“Button”)
})
.sheet(item: $activeSheet) { sheet in
switch sheet {
case .info:
InfoView()
case .settings:
SettingsView()
}
}
SettingsView:
struct SettingsView: View {
@Environment(\.presentationMode) private var presentationMode
@EnvironmentObject var model: MainModel
var body: some View {
Button("Action") {
model.myFunction()
}
}
}
In my InfoView-sheet I have a button that calls a function inside an EnvironmentObject. How do I dismiss the sheet once the function has completed in the EnvironmentObject?
Every view is linked to the same EnvironmentObject btw.
Thanks!
Depending for which min iOS version you are deploying, you have two options:
If your minimum iOS version is <= iOS 14, in both InfoView and SettingsView use system environment \.presentationMode.
struct SettingsView: View {
@EnvironmentObject var model: MainModel
@Environment(\.presentationMode) private var presentationMode
var body: some View {
Button("Dismiss") {
/// ... Do something here prior to dismissing the sheet.
model.MyFunction(email: email, password: password) {
presentationMode.wrappedValue.dismiss()
}
}
}
}
On your minimum iOS version is iOS 15, in both InfoView and SettingsView use system environment \.dismiss.
struct SettingsView: View {
@EnvironmentObject var model: MainModel
@Environment(\.dismiss) private var dismiss
var body: some View {
Button("Dismiss") {
/// ... Do something here prior to dismissing the sheet.
model.MyFunction(email: email, password: password) {
dismiss()
}
}
}
}
And MainModel class:
class MainModel: ObservableObject {
func myFunction(email: String, password: String, onSuccess: (() -> Void)? = nil) {
auth.signIn(withEmail: email, password: password) { [weak self] result, error in
if result == nil, error != nil {
self?.showAlert = true
} else {
guard result != nil, error == nil else { return }
/* Success */
self?.signedIn = true
onSuccess?()
}
}
}
}
Alternative solution:
If your minimum deployment target is >= iOS 14, you can listen to changes of your environment object properties like this:
struct SettingsView: View {
@EnvironmentObject var model: MainModel
@Environment(\.dismiss) private var dismiss
var body: some View {
Button("Dismiss") {
model.MyFunction(email: email, password: password)
}
.onChange(of: model.signedIn) { signedIn in
if signedIn {
dismiss()
}
}
}
}