How to Add Textfield to Uialertcontroller in Swift

How to add TextField to UIAlertController in Swift

Swift 5.1

alert.addTextField { (textField) in
textField.placeholder = "Enter First Name"
}

Use this code, I am running this code in my app successfully.

@IBAction func addButtonClicked(sender : AnyObject){
let alertController = UIAlertController(title: "Add New Name", message: "", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addTextFieldWithConfigurationHandler { (textField : UITextField!) -> Void in
textField.placeholder = "Enter Second Name"
}
let saveAction = UIAlertAction(title: "Save", style: UIAlertActionStyle.Default, handler: { alert -> Void in
let firstTextField = alertController.textFields![0] as UITextField
let secondTextField = alertController.textFields![1] as UITextField
})
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Default, handler: {
(action : UIAlertAction!) -> Void in })
alertController.addTextFieldWithConfigurationHandler { (textField : UITextField!) -> Void in
textField.placeholder = "Enter First Name"
}

alertController.addAction(saveAction)
alertController.addAction(cancelAction)

self.presentViewController(alertController, animated: true, completion: nil)
}

Edited: Swift 3.0 version

@IBAction func addButtonClicked(_ sender: UIButton){
let alertController = UIAlertController(title: "Add New Name", message: "", preferredStyle: .alert)
alertController.addTextField { (textField : UITextField!) -> Void in
textField.placeholder = "Enter Second Name"
}
let saveAction = UIAlertAction(title: "Save", style: .default, handler: { alert -> Void in
let firstTextField = alertController.textFields![0] as UITextField
let secondTextField = alertController.textFields![1] as UITextField
print("firstName \(firstTextField.text), secondName \(secondTextField.text)")
})
let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: { (action : UIAlertAction!) -> Void in })
alertController.addTextField { (textField : UITextField!) -> Void in
textField.placeholder = "Enter First Name"
}

alertController.addAction(saveAction)
alertController.addAction(cancelAction)

self.present(alertController, animated: true, completion: nil)
}

How to add textField in UIAlertController?

You can add multiple textfields to alert controller and access them with the alert controller's textFields property

If the new password is an empty string, present the alert again. Or another way would be to disable the "Confirm" button, enabling it only when text field has text.

UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"confirm the modification" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
UITextField *password = alertController.textFields.firstObject;
if (![password.text isEqualToString:@""]) {

//change password

}
else{
[self presentViewController:alertController animated:YES completion:nil];
}
}];

How do I observe user editing a textField in an UIAlertController?

You can try to get a reference to it with self.textF = alert.textFields?[0]

class ViewController: UIViewController {

var textF:UITextField!

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {

//1. Create the alert controller.
let alert = UIAlertController(title: "Some Title", message: "Enter a text", preferredStyle: .alert)
alert.addTextField { (textField) in
textField.text = "Some default text"
}
let tex = alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] (_) in

}))
// 4. Present the alert.
self.present(alert, animated: true, completion: nil)

self.textF = alert.textFields?[0]

self.textF.addTarget(self, action: #selector(self.textFieldDidChange), for: UIControl.Event.editingChanged)

}

}

@objc func textFieldDidChange() {
print(textF.text)
}

}

Custom TextField in UIAlertController]

I do not think that it's possible to use a UITextField subclass in an UIAlertController. You can only edit the textfield's properties in the configuration handler.

How to add a TextField to UIAlertView in Swift

You can access the textfield with:

let textField = alert.textFieldAtIndex(0)

Then to change the placeholder text:

textField.placeholder = "Foo!"

And the keyboard type:

textField.keyboardType = ...

show the textField in the alertController in swift

Code for Adding textField in UIALertController :

let alertController = UIAlertController(title: "PlainTextStyle", message: "PlainTextStyle AlertView.", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addTextFieldWithConfigurationHandler { (textField : UITextField) -> Void in
textField.placeholder = "Login"
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) { (result : UIAlertAction) -> Void in
print("Cancel")
}
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default) { (result : UIAlertAction) -> Void in
print(alertController.textFields?.first?.text)
}
alertController.addAction(cancelAction)
alertController.addAction(okAction)
self.presentViewController(alertController, animated: true, completion: nil)

Update Swift 3.0

 let alertController = UIAlertController(title: "PlainTextStyle", message: "PlainTextStyle AlertView.", preferredStyle: UIAlertControllerStyle.alert)
alertController.addTextField { (textField : UITextField) -> Void in
textField.placeholder = "Login"
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel) { (result : UIAlertAction) -> Void in
}
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
}
alertController.addAction(cancelAction)
alertController.addAction(okAction)
self.present(alertController, animated: true, completion: nil)

TextField in UIALertController :

Sample Image

How can i change uialertcontroller's textfield content?

You need to add the text field before you would access it

here is an example

let alertController = UIAlertController(title: "Update Name", message: nil, preferredStyle: .alert)

alertController.addTextField { textField in
textField.text = "Text goes here 1"
textField.placeholder = "placeholder"
textField.tag = 0
}

alertController.addTextField { textField in
textField.text = "Text goes here 2"
textField.tag = 1
}

alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { _ in

let firstTextField = alertController.textFields?.first
let secondTextField = alertController.textFields?.last

print(firstTextField?.text, secondTextField?.text)
}))

Edit

Thanks to @rmaddy

The problem with question's code is that it's trying to set the text field's text after the alert has been dismissed. This makes little sense. Once a user taps one of the alert buttons, the user has already entered text into the text field. The code should be trying to read the user's entered text from the text field, not trying to update the text field's text.

UIAlertController with textfield validation alert displaying issue in swift ios

you just need to put UILabel code outside of "Create" UIAlertAction block like this.

This line (inside the Create action block) causes the issue --> dialogMessage.view.addSubview(label)

I hope this will help you.

func alertControllerWithTf() {
let dialogMessage = UIAlertController(title: "New Room", message: nil, preferredStyle: .alert)
let label = UILabel(frame: CGRect(x: 0, y: 40, width: 270, height:18))
label.textAlignment = .center
label.textColor = .red
label.font = label.font.withSize(12)
dialogMessage.view.addSubview(label)
label.isHidden = true

let Create = UIAlertAction(title: "Create", style: .default, handler: { (action) -> Void in
if let userInput = self.roomTextField!.text {
if userInput == "" {
label.text = ""
label.text = "Please enter room name to create."
label.isHidden = false
self.present(dialogMessage, animated: true, completion: nil)

}
else if self.haveSameRoomName(createdRoomName: userInput){
label.text = ""
label.text = "You've already created room with this name."
label.isHidden = false
self.present(dialogMessage, animated: true, completion: nil)
}
else{
print("Create button success block called do stuff here....")
}
}
})
let cancel = UIAlertAction(title: "Cancel", style: .default) { (action) -> Void in
print("Cancel button tapped")
}

//Add OK and Cancel button to dialog message

dialogMessage.addAction(Create)
dialogMessage.addAction(cancel)
// Add Input TextField to dialog message
dialogMessage.addTextField { (textField) -> Void in
self.roomTextField = textField
self.roomTextField?.placeholder = "Please enter room name"
}

// Present dialog message to user
self.present(dialogMessage, animated: true, completion: nil)
}

How to add UIDatePicker into textField in UIAlertController?

You can add like this

let datePicker = UIDatePicker()
let toDoAlert = UIAlertController(title: "Add ToDo", message: "Add a new task", preferredStyle: .alert)
toDoAlert.addTextField { textField in
textField.inputView = self.datePicker
}

Or

let datePicker = UIDatePicker()
let toDoAlert = UIAlertController(title: "Add ToDo", message: "Add a new task", preferredStyle: .alert)
toDoAlert.addTextField()
toDoAlert.textFields?.first?.inputView = datePicker

And for setting the picker value.

let datePicker = UIDatePicker()
let toDoAlert = UIAlertController(title: "Add ToDo", message: "Add a new task", preferredStyle: .alert)

@IBAction func showAlert(_ sender: UIButton) {
datePicker.addTarget(self, action: #selector(dateChangeEvent), for: .valueChanged)
toDoAlert.addTextField { textField in
textField.inputView = self.datePicker
}
//=== Other Code ====
}

@objc private func dateChangeEvent(_ datePicker: UIDatePicker) {
toDoAlert.textFields?.first?.text = datePicker.date.description
}

How to add a TextField to Alert in SwiftUI?

As the Alert view provided by SwiftUI doesn't do the job you will need indeed to use UIAlertController from UIKit. Ideally we want a TextFieldAlert view that we can presented in the same way we would present the Alert provided by SwiftUI:

struct MyView: View {

@Binding var alertIsPresented: Bool
@Binding var text: String? // this is updated as the user types in the text field

var body: some View {
Text("My Demo View")
.textFieldAlert(isPresented: $alertIsPresented) { () -> TextFieldAlert in
TextFieldAlert(title: "Alert Title", message: "Alert Message", text: self.$text)
}
}
}

We can achieve this writing a couple of classes and adding a modifier in a View extension.

1) TextFieldAlertViewController creates a UIAlertController (with a text field of course) and presents it when it appears on screen. User changes to the text field are reflected into a Binding<String> that is passed during initializazion.

class TextFieldAlertViewController: UIViewController {

/// Presents a UIAlertController (alert style) with a UITextField and a `Done` button
/// - Parameters:
/// - title: to be used as title of the UIAlertController
/// - message: to be used as optional message of the UIAlertController
/// - text: binding for the text typed into the UITextField
/// - isPresented: binding to be set to false when the alert is dismissed (`Done` button tapped)
init(title: String, message: String?, text: Binding<String?>, isPresented: Binding<Bool>?) {
self.alertTitle = title
self.message = message
self._text = text
self.isPresented = isPresented
super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// MARK: - Dependencies
private let alertTitle: String
private let message: String?
@Binding private var text: String?
private var isPresented: Binding<Bool>?

// MARK: - Private Properties
private var subscription: AnyCancellable?

// MARK: - Lifecycle
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
presentAlertController()
}

private func presentAlertController() {
guard subscription == nil else { return } // present only once

let vc = UIAlertController(title: alertTitle, message: message, preferredStyle: .alert)

// add a textField and create a subscription to update the `text` binding
vc.addTextField { [weak self] textField in
guard let self = self else { return }
self.subscription = NotificationCenter.default
.publisher(for: UITextField.textDidChangeNotification, object: textField)
.map { ($0.object as? UITextField)?.text }
.assign(to: \.text, on: self)
}

// create a `Done` action that updates the `isPresented` binding when tapped
// this is just for Demo only but we should really inject
// an array of buttons (with their title, style and tap handler)
let action = UIAlertAction(title: "Done", style: .default) { [weak self] _ in
self?.isPresented?.wrappedValue = false
}
vc.addAction(action)
present(vc, animated: true, completion: nil)
}
}

2) TextFieldAlert wraps TextFieldAlertViewController using the UIViewControllerRepresentable protocol so that it can be used within SwiftUI.

struct TextFieldAlert {

// MARK: Properties
let title: String
let message: String?
@Binding var text: String?
var isPresented: Binding<Bool>? = nil

// MARK: Modifiers
func dismissable(_ isPresented: Binding<Bool>) -> TextFieldAlert {
TextFieldAlert(title: title, message: message, text: $text, isPresented: isPresented)
}
}

extension TextFieldAlert: UIViewControllerRepresentable {

typealias UIViewControllerType = TextFieldAlertViewController

func makeUIViewController(context: UIViewControllerRepresentableContext<TextFieldAlert>) -> UIViewControllerType {
TextFieldAlertViewController(title: title, message: message, text: $text, isPresented: isPresented)
}

func updateUIViewController(_ uiViewController: UIViewControllerType,
context: UIViewControllerRepresentableContext<TextFieldAlert>) {
// no update needed
}
}

3) TextFieldWrapper is a simple ZStack with a TextFieldAlert on the back (only if isPresented is true) and a presenting view on the front. The presenting view is the only one visibile.

struct TextFieldWrapper<PresentingView: View>: View {

@Binding var isPresented: Bool
let presentingView: PresentingView
let content: () -> TextFieldAlert

var body: some View {
ZStack {
if (isPresented) { content().dismissable($isPresented) }
presentingView
}
}
}

4) The textFieldAlert modifier allows us to smoothly wrap any SwiftUI view in a TextFieldWrapper and obtain the desired behaviour.

extension View {
func textFieldAlert(isPresented: Binding<Bool>,
content: @escaping () -> TextFieldAlert) -> some View {
TextFieldWrapper(isPresented: isPresented,
presentingView: self,
content: content)
}
}


Related Topics



Leave a reply



Submit