skip to Main Content

Please help me get rid of this problem:

Steps to reproduce my problem:

  1. Tap "Edit My Name" Button

  2. Inside .sheet, tap on the TextField and then with keyboard still shown, scroll all the way down

  3. Tap on the Button "Delete Name"

  4. Here is the problem:

    confirmationDialog appears only for one second, and then
    disappears, not giving the user any chance (or less than one second chance)
    to tap one of the confirmationDialog’s Buttons!

Here’s my code:

ContentView.swift

import SwiftUI

struct ContentView: View {
    @State private var myName = "Joe"
    @State private var isEditingName = false
    
    var body: some View {
        Text("My name is: (myName)")
        Button("Edit My Name") {
            isEditingName = true
        }
        .padding()
        .sheet(isPresented: $isEditingName) {
            EditView(name: $myName)
        }
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

EditView.swift

import SwiftUI

struct EditView: View {
    @Binding var name: String
    @State private var isShowingConfirmationDialog = false
    
    var body: some View {
        Form {
            Section {
                TextField("Name", text: $name)
            }
            Section {
                VStack {
                    ForEach(0..<50, id: .self) { number in
                        Text("(number)")
                    }
                }
            }
            Section {
                deleteNameWithConfirmationDialog
            }
        }
    }
    
    private var deleteNameWithConfirmationDialog: some View {
        Button("Delete Name", role: .destructive) {
            isShowingConfirmationDialog = true
        }
        .confirmationDialog("Are you sure you want to delete name?", isPresented: $isShowingConfirmationDialog) {
            Button("Delete Name", role: .destructive) {
                name = ""
            }
            Button("Cancel", role: .cancel) { }
        } message: {
            Text("Are you sure you want to delte name?")
        }
    }
    
}

struct EditView_Previews: PreviewProvider {
    static var previews: some View {
        EditView(name: .constant(String("Joe")))
    }
}

2

Answers


  1. It works if you move the .confirmationDialogue out of the Form:

    struct EditView: View {
        @Binding var name: String
        @State private var isShowingConfirmationDialog = false
        
        var body: some View {
    
            Form {
                Section {
                    TextField("Name", text: $name)
                }
                Section {
                    VStack {
                        ForEach(0..<50, id: .self) { number in
                            Text("(number)")
                        }
                    }
                }
                Section {
                    Button("Delete Name", role: .destructive) {
                        isShowingConfirmationDialog = true
                    }
                }
            }
            
            .confirmationDialog("Are you sure you want to delete name?", isPresented: $isShowingConfirmationDialog) {
                Button("Delete Name", role: .destructive) {
                    name = ""
                }
                Button("Cancel", role: .cancel) { }
            } message: {
                Text("Are you sure you want to delete name?")
            }
        }
    }
    
    Login or Signup to reply.
  2. If you want to keep .confirmationDialog inside of the Form, or if you are using .confirmationDialog to manage deleting items within a List, you can also avoid the immediate dismissal by excluding the .destructive role from the deleteButton in .swipeActions.

    var body: some View {
        List { // this could also be a Form
            ForEach(listItems) { item in 
                ItemRow(item: item) // confirmationDialog is in ItemRow
            }.swipeActions { 
                Button(action: { /* deleteMethodHere */ }) { 
                    Image(systemName: "trash") 
                }.tint(.red) // to keep the swipe button red
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search