Search code examples
swiftuialertcontrollertextinput

How to get text input out of UIAlertcontroller OR how to wait for the input using Swift


I am trying to present an Alertcontroller that prompts the user for a filename and then use the filename elsewhere in the program. I have been trying numerous variations of the following code:

import UIKit

class ViewController: UIViewController {

var shortName: String!

@IBAction func saveFile(sender: AnyObject) {

       //request filename with alert

    var alertController:UIAlertController?
    alertController = UIAlertController(title: "Enter File",
        message: "Enter file name below",
        preferredStyle: .Alert)

    alertController!.addTextFieldWithConfigurationHandler(
        {(textField: UITextField!) in
            textField.placeholder = ""
    })

    let action = UIAlertAction(title: "Submit",
        style: UIAlertActionStyle.Default,
        handler: {[weak self]
            (paramAction:UIAlertAction!) in
            if let textFields = alertController?.textFields{
                let theTextFields = textFields as [UITextField]
                let enteredText = theTextFields[0].text
                self!.shortName = enteredText      //trying to get text into shortName
                print(self!.shortName)             // prints
            }
        })

    alertController?.addAction(action)
    self.presentViewController(alertController!,
        animated: true,
        completion: nil)

 //do some stuff with the input

    print(shortName)  //THIS RETURNS nil if uncommented. comment out to avoid crash

}


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

I have thoroughly researched this and can't find how to either:

  1. get the string value of shortName out of the UIAlertAction closure and into the shortName (I know that the current "self!.shortName" is unavailable outside the closure - doesn't matter what name I use - can't get it out)

  2. If you run the program "as-is", the print(shortName) line will cause a crash due to unwrapping of nil. How can I get the alert to "wait" for input?

Most of the posted "solutions" have the same problem - they don't actually get the text input out of the closure and into a variable that can be accessed by the rest of the program.

thanks


Solution

  • Of course you get crash, shortName is nil while Submit button isn't pressed. You can try something like this:

    @IBAction func saveFile(sender: AnyObject) {
    
    var alertController:UIAlertController?
    alertController = UIAlertController(title: "Enter File",
        message: "Enter file name below",
        preferredStyle: .Alert)
    
    alertController!.addTextFieldWithConfigurationHandler(
        {(textField: UITextField!) in
            textField.placeholder = ""
    })
    
    let action = UIAlertAction(title: "Submit",
        style: UIAlertActionStyle.Default,
        handler: {[weak self]
            (paramAction:UIAlertAction!) in
            if let textFields = alertController?.textFields{
                let theTextFields = textFields as [UITextField]
                let enteredText = theTextFields[0].text
                self!.shortName = enteredText      //trying to get text into shortName
                print(self!.shortName)             // prints
    
                self?.handleText()
    
                NSOperationQueue.mainQueue().addOperationWithBlock({
                    self?.handleTextInMainThread()
                })
            }
        })
    
        alertController?.addAction(action)
        self.presentViewController(alertController!,
            animated: true,
            completion: nil)
    }
    
    func handleText() {
        print(self.shortName)
    }
    
    func handleTextInMainThread() {
        print(self.shortName)
    }
    

    You have use NSOperationQueue if you want to work with UI inside handleTextInMainThread after user's input.