Swift - Store UIAlterController text value - swift

(Using Swift 2 and Xcode 7)
I have a UIAlertController that prompt the user the enter a name.
I'm having difficulties getting the value that the user enters, so any heads up would be great.
I have the following code;
func promptUserToEnterSessionName() -> String{
let sessionNameController = UIAlertController(title: "Save your yoga session", message: "Please enter session name", preferredStyle: .Alert)
let cancelAction = (UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
let saveAction = (UIAlertAction(title: "Save", style: UIAlertActionStyle.Default, handler: enteredSessionName))
sessionNameController.addTextFieldWithConfigurationHandler {
(textField) -> Void in
self.sessionName = textField
}
sessionNameController.addAction(cancelAction)
sessionNameController.addAction(saveAction)
self.presentViewController(sessionNameController, animated: true, completion: nil)
//savedSessionName = (sessionNameController.textFields![0] as UITextField).text!
//print(savedSessionName)
return ""
}
func enteredSessionName(alert: UIAlertAction!){
print("sessionName" + String(sessionName))
}

So another possible solution is to save the whole UITextField in your member variable.
var textField: UITextField?
sessionNameController.addTextFieldWithConfigurationHandler {
(textField) -> Void in
self.textField = textField
}
func enteredSessionName(alert: UIAlertAction!){
print("sessionName" + String(self.textField.text))
}

Related

UIAlertController freezes in Swift 5 when using addTextField (target iOS12.4) - Transitioning from Objective C

My Swift view controller is called from my mainly Objective C app. Calling function 'showAlert()' displays, but freezes the emulator. I get no error, but none of the buttons work and the textfield doesn't raise the keyboard (the placeholder shows up). (My actual code has more alertActions, which work fine if I comment out the TextField code). I even copied verbatim code from StackOverflow to display a basic alert controller with a TextField, and it has the same issue as written below.
#objc class MyVC :UIViewController {
#objc func showAlert() {
let alertController = UIAlertController(title: "Title", message: "", preferredStyle: .alert)
alertController.addTextField { (textField : UITextField!) -> Void in
textField.placeholder = "Enter name"
}
let saveAction = UIAlertAction(title: "Confirm", style: .default, handler: { alert -> Void in
if let textField = alertController.textFields?[0] {
if textField.text!.count > 0 {
print("Text :: \(textField.text ?? "")")
}
}
})
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {
(action : UIAlertAction!) -> Void in })
alertController.addAction(cancelAction)
alertController.addAction(saveAction)
alertController.preferredAction = saveAction
self.present(alertController, animated: true, completion: nil)
}
}
A breakpoint at 'present(...' show the alert controller allocated, but stepping in from here ends with the frozen display of the alertcontroller. Any debug suggestions greatly appreciated.

Swift4 - Multiple Alerts with Text Field - Completion Handler

i am working at my startscreen (viewDidAppear). At the beginning of the app, there should be an alert with some notice message. This works fine. After you click "ok" at the notice, the next alert should pop up with a text field. In this text field you have to type in a double value. I need this double value to set up a lot of things inside the app, so I need this value outside the function to calculate with it.
E.g. The notice message describes how the app works. You click OK. Now the next alert pop up with the text field. For example it asks your height. After you type in your height and click OK the height-value is the main part of different calculations.
The problem is now, that my app works with the nil-value before I typed in the double value (e.g. height)
These are the snippets from the code.
var iNeedTheDataHere:String?
///Alerts
//Start
let startController = UIAlertController(title: "Notice", message: "notice message ", preferredStyle: .alert)
let inputController = UIAlertController(title: "Set input", message: "Please set the input", preferredStyle: .alert)
//BeforeScreenLoad
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Start Alert
startController.addAction(UIAlertAction(title: "OK", style: .default, handler:{(action:UIAlertAction!) in
self.input()
}))
self.present(startController, animated: true)
}
func input() {
inputController.addTextField()
let submitAction = UIAlertAction(title: "Submit", style: .default) { [unowned ac] _ in
let answer = inputController.textFields![0].text
iNeedTheDataHere = answer
}
inputController.addAction(submitAction)
}
When I set Breakpoints, I see that the value of the inputController is set to nil, before I typed in anything. I guess my mistake has something to do with the handler
Sorry for my English
Hope somebody can help me
let alert = UIAlertController(title: "Alert!!!", message: "Please enter your message ", preferredStyle: .alert)
alert.addTextField(configurationHandler: self.configurationTextField)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler:{ (UIAlertAction) in
self.number.text?=""
MBProgressHUD.hide(for: self.view, animated: true)
}))
alert.addAction(UIAlertAction(title: "Done", style: .default, handler:{ (UIAlertAction) in
}))
self.present(alert, animated: true, completion: {
})
I have made some changes in your code to achieve that:
class ViewController: UIViewController {
let startController = UIAlertController(title: "Notice", message: "notice message ", preferredStyle: .alert)
let inputController = UIAlertController(title: "Set input", message: "Please set the input", preferredStyle: .alert)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(_ animated: Bool) {
startController.addAction(UIAlertAction(title: "OK", style: .default, handler:{(action:UIAlertAction!) in
self.input()
}))
self.present(startController, animated: true)
}
func input() {
//Present another alert with textField
let confirmAction = UIAlertAction(title: "Submit", style: .default) { (_) in
guard let textFields = self.inputController.textFields,
textFields.count > 0 else {
// Could not find textfield
return
}
//get your textField
let answerTF = textFields[0]
let answer = answerTF.text
//Get values entered by user
print(answer)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }
//add your textField here
inputController.addTextField { (textField) in
//Set a placeholde for textField
textField.placeholder = "Answer"
}
inputController.addAction(confirmAction)
inputController.addAction(cancelAction)
self.present(inputController, animated: true, completion: nil)
}
}
I have added comment to explain what I am doing.
And your result will be:
You can also check demo project here.

my segue is not working

I have a button that if user click on it it must show another vc and it's working properly until I add UIAlertController which it's getting data from user and after user click done on alertaction nothing happens
this is my code:
#IBAction func DfsClicked(_ sender: AnyObject) {
let alertController = UIAlertController(title: "DFS?", message: "Please input DFS depth:", preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "Confirm", style: .default) { (_) in
if let field = alertController.textFields?[0] {
// store your data
self.depth = Int(field.text!)!
print(self.depth)
Puzzle.AnswerNode = dfs(inputdepth: self.depth,SortedPuzzle:self.SortedPuzzle)
} else {
// user did not fill field
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }
alertController.addTextField { (textField) in
textField.placeholder = "Default is 2"
textField.keyboardType = UIKeyboardType.numberPad
}
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true)
}
Use this method to perform segue, inside confirm action block
self.performSegue(withIdentifier: <Identifier>, sender: <Any?>)

Getting text value from alert box

I'm having problems getting a text fields value from a UIAlertController. I am getting the value, but It seems to be executing my code in the wrong order. In the function below, I expect the function call to return a string, but the value is not set at the time the function returns.
#IBAction func btnSaveSession(sender: AnyObject) {
//Prompt user to enter session name
var sessionName: String = ""
sessionName = promptUserToEnterSessionName("Save Session", message: "Please enter the name of your custom session below.");
print("session Name: " + sessionName)
//Save session to firebase.
//redirect to create session controller.
}
func promptUserToEnterSessionName(title: String, message: String) -> String{
var sessionName: String = ""
//1. Create the alert controller.
let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
//2. Add the text field. You can configure it however you need.
alert.addTextFieldWithConfigurationHandler({ (textField) -> Void in
textField.text = "Enter session name."
})
//3. Grab the value from the text field, and print it when the user clicks OK.
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in
let textField = alert.textFields![0] as UITextField
print("Text field: \(textField.text)")
sessionName = textField.text!
}))
// 4. Present the alert.
self.presentViewController(alert, animated: true, completion: nil)
return sessionName
}
If anyone is having problems understanding my question, please comment and I will do my best to explain.
your ok action handler(closure) will call when you click on ok button. so instead of assign value to local variable sessionName , make a sessionName variable in class.
class YourClass {
var sessionName: String?
...
#IBAction func btnSaveSession(sender: AnyObject) {
//Prompt user to enter session name
promptUserToEnterSessionName("Save Session", message: "Please enter the name of your custom session below.");
}
func promptUserToEnterSessionName(title: String, message: String) {
//1. Create the alert controller.
let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
//2. Add the text field. You can configure it however you need.
alert.addTextFieldWithConfigurationHandler({ (textField) -> Void in
textField.text = "Enter session name."
})
//3. Grab the value from the text field, and print it when the user clicks OK.
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in
let textField = alert.textFields![0] as UITextField
print("Text field: \(textField.text)")
self.sessionName = textField.text!
self.testDemo()
}))
// 4. Present the alert.
self.presentViewController(alert, animated: true, completion: nil)
}
fun TestDemo() {
print("session Name: " + self.sessionName)
//Save session to firebase.
//redirect to create session controller.
}
}
You can use a Callback to get the value, like this:
func AlertPrompt(vista:UIViewController, titulo:String , mensaje:String, aceptar:String, completion: #escaping (_ resultado: String)->()) {
let miAlerta = UIAlertController(title: titulo, message: mensaje, preferredStyle: UIAlertControllerStyle.alert)
miAlerta.addTextField(configurationHandler: {
(textField) -> Void in
})
let okBoton = UIAlertAction(title: aceptar, style: UIAlertActionStyle.default, handler: {
(action) -> Void in
let result = miAlerta.textFields![0] as UITextField
// You return the value here
completion(result.text! as String)
})
miAlerta.addAction(okBoton)
let cancelBoton = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)
miAlerta.addAction(cancelBoton)
vista.present(miAlerta, animated: true, completion: nil)
}
And call the function like this:
AlertPrompt(vista: self, titulo: "Title", mensaje: "some message", aceptar: "Acept"){(resultado)->() in
print(resultado)
}
That works perfect for me, hope this help
This code:
let textField = alert.textFields![0] as UITextField
print("Text field: \(textField.text)")
sessionName = textField.text!
will be called only at the moment the button corresponding to the defined action is clicked. So at the moment of creation the UIAlertController it's not called.
Read about blocks in Swift, it should be clearer then.

AlertView with textbox, how to gather the data from entered textbox

Would like to gather the data from a AlertView out from the textbox. What I've found in the www is this:
#IBAction func showAlertTapped(sender: AnyObject) {
//Create the AlertController
let actionSheetController: UIAlertController = UIAlertController(title: "Add User", message: "Enter username", preferredStyle: .Alert)
//Create and add the Cancel action
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
//Do some stuff
}
actionSheetController.addAction(cancelAction)
//Create and an option action
let saveAction: UIAlertAction = UIAlertAction(title: "Save", style: .Default) { action -> Void in
//Do some other stuff
}
actionSheetController.addAction(saveAction)
//Add a text field
actionSheetController.addTextFieldWithConfigurationHandler { textField -> Void in
//TextField configuration
textField.textColor = UIColor.blueColor()
}
//Present the AlertController
self.presentViewController(actionSheetController, animated: true, completion: nil)
}
Im not aware of the functionality of the AlertController, so I don't know where to bring the entred text to a e.g. simple variable?
Looks like UIAlertController has a textFields property and since you only have one text field you should be able to access it in the following way
let textField = actionSheetController.textFields?.first as UITextField
You can access the textfields string by assigning it to a local variable in the configuration handler.
//Create a local variable
var alertTextField:UITextField?
//Create the AlertController
let actionSheetController: UIAlertController = UIAlertController(title: "Add User", message: "Enter username", preferredStyle: .Alert)
//Create and add the Cancel action
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
//Do some stuff
}
actionSheetController.addAction(cancelAction)
//Create and add save action
let saveAction: UIAlertAction = UIAlertAction(title: "Save", style: .Default) { action -> Void in
//Unwrap your local variable and access your textfield
if let textField = alertTextField {
println("\(textField.text)")
}
}
actionSheetController.addAction(saveAction)
//Add a text field
actionSheetController.addTextFieldWithConfigurationHandler { textField -> Void in
//TextField configuration
textField.textColor = UIColor.blueColor()
//Assign your UIAlertController textField to your local variable
alertTextField = textField
}
//Present the AlertController
self.presentViewController(actionSheetController, animated: true, completion: nil)
Swift 3 version:
//Create a local variable
var alertTextField:UITextField?
//Create the AlertController
let actionSheetController: UIAlertController = UIAlertController(title: "Add User", message: "Enter username", preferredStyle: .alert)
//Create and add the Cancel action
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .cancel) { action -> Void in
//Do some stuff
}
actionSheetController.addAction(cancelAction)
//Create and add save action
let saveAction: UIAlertAction = UIAlertAction(title: "Save", style: .default) { action -> Void in
//Unwrap your local variable and access your textfield
if let textField = alertTextField {
print(textField.text!)
}
}
actionSheetController.addAction(saveAction)
//Add a text field
actionSheetController.addTextField { textField -> Void in
//TextField configuration
textField.textColor = UIColor.blue
//Assign your UIAlertController textField to your local variable
alertTextField = textField
}
//Present the AlertController
self.present(actionSheetController, animated: true, completion: nil)