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
How to Convert Double to Int in Swift
Getting a "This Application Is Modifying the Autolayout Engine from a Background Thread" Error
How to Use Swift 4 Codable in Core Data
How to Run a Terminal Command in a Swift Script? (E.G. Xcodebuild)
Nsobject Subclass in Swift: Hash VS Hashvalue, Isequal VS ==
Alamofire Get API Request Not Working as Expected
How to Resolve "Ambiguous Use Of" Compile Error With Swift #Selector Syntax
Swift 3 Incorrect String Interpolation With Implicitly Unwrapped Optionals
Any Way to Replace Characters on Swift String
How to Deal With @Objc Inference Deprecation With #Selector() in Swift 4
Is Swift Pass by Value or Pass by Reference
How Does One Generate a Random Number in Swift
Difference Between 'Let' and 'Var' in Swift
Nsdate() or Date() Shows the Wrong Time
How to Check If a String Contains Another String in Swift
Structure VS Class in Swift Language
Inter-App Data Migration (Migrating Data to New App Version)
Number of Words in a Swift String For Word Count Calculation