How to add a TextField to Alert in SwiftUI?

Captain Vril picture Captain Vril · Jun 23, 2019 · Viewed 12.4k times · Source

Anyone an idea how to create an Alert in SwiftUI that contains a TextField?

sample_image

Answer

Matteo Pacini picture Matteo Pacini · Jun 24, 2019

Alert is quite limited at the moment, but you can roll your own solution in pure SwiftUI.

Here's a simple implementation of a custom alert with a text field.

struct TextFieldAlert<Presenting>: View where Presenting: View {

    @Binding var isShowing: Bool
    @Binding var text: String
    let presenting: Presenting
    let title: String

    var body: some View {
        GeometryReader { (deviceSize: GeometryProxy) in
            ZStack {
                self.presenting
                    .disabled(isShowing)
                VStack {
                    Text(self.title)
                    TextField(self.$text)
                    Divider()
                    HStack {
                        Button(action: {
                            withAnimation {
                                self.isShowing.toggle()
                            }
                        }) {
                            Text("Dismiss")
                        }
                    }
                }
                .padding()
                .background(Color.white)
                .frame(
                    width: deviceSize.size.width*0.7,
                    height: deviceSize.size.height*0.7
                )
                .shadow(radius: 1)
                .opacity(self.isShowing ? 1 : 0)
            }
        }
    }

}

And a View extension to use it:

extension View {

    func textFieldAlert(isShowing: Binding<Bool>,
                        text: Binding<String>,
                        title: String) -> some View {
        TextFieldAlert(isShowing: isShowing,
                       text: text,
                       presenting: self,
                       title: title)
    }

}

Demo:

enter image description here

struct ContentView : View {

    @State private var isShowingAlert = false
    @State private var alertInput = ""

    var body: some View {
        NavigationView {
            VStack {
                Button(action: {
                    withAnimation {
                        self.isShowingAlert.toggle()
                    }
                }) {
                    Text("Show alert")
                }
            }
            .navigationBarTitle(Text("A List"), displayMode: .large)
        }
        .textFieldAlert(isShowing: $isShowingAlert, text: $alertInput, title: "Alert!")
    }
}