Swiftui Dismiss Modal

Dismiss modal automatically after 1 sec of being shown - swiftui

If I get what you are asking, a solution is to use DispatchQueue.main.asyncAfter():

//to show rejection transition
.fullScreenCover(isPresented: $isPresented, content: {
FullScreenModalView.init()
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
isPresented = false
}

})

Please note that this may not be exactly precise as the firing time depends upon how busy the OS is at that moment, but it will generally be very good. Also, you generally want some user interaction in dismissing a modal as the user may look away in the second you display it.

SwiftUI: Close modal sheet programmatically from a function inside an Environment Object

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()
}
}
}
}

SwiftUI: close modal

Beta 6

Use presentationMode from the @Environment.

struct SomeView: View {
@Environment(\.presentationMode) var presentationMode

var body: some View {
VStack {
Text("Ohay!")
Button("Close") {
self.presentationMode.wrappedValue.dismiss()
}
}
}
}

Dismiss a parent modal in SwiftUI from a NavigationView

Here is possible approach based on usage own explicitly created environment key (actually I have feeling that it is not correct to use presentationMode for this use-case.. anyway).

Proposed approach is generic and works from any view in modal view hierarchy. Tested & works with Xcode 11.2 / iOS 13.2.

// define env key to store our modal mode values
struct ModalModeKey: EnvironmentKey {
static let defaultValue = Binding<Bool>.constant(false) // < required
}

// define modalMode value
extension EnvironmentValues {
var modalMode: Binding<Bool> {
get {
return self[ModalModeKey.self]
}
set {
self[ModalModeKey.self] = newValue
}
}
}


struct ParentModalTest: View {
@State var showModal: Bool = false

var body: some View {
Button(action: {
self.showModal.toggle()
}) {
Text("Launch Modal")
}
.sheet(isPresented: self.$showModal, onDismiss: {
}) {
PageOneContent()
.environment(\.modalMode, self.$showModal) // < bind modalMode
}
}
}

struct PageOneContent: View {
var body: some View {
NavigationView {
VStack {
Text("I am Page One")
}
.navigationBarTitle("Page One")
.navigationBarItems(
trailing: NavigationLink(destination: PageTwoContent()) {
Text("Next")
})
}
}
}

struct PageTwoContent: View {

@Environment (\.modalMode) var modalMode // << extract modalMode

var body: some View {
NavigationView {
VStack {
Text("This should dismiss the modal. But it just pops the NavigationView")
.padding()

Button(action: {
self.modalMode.wrappedValue = false // << close modal
}) {
Text("Finish")
}
.padding()
.foregroundColor(.white)
.background(Color.blue)
}
.navigationBarTitle("Page Two")
}
}
}

backup



Related Topics



Leave a reply



Submit