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!
CodePudding user response:
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()
}
}
}
}