Jeff E
Jeff E

Reputation: 63

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

Upvotes: 1

Views: 815

Answers (2)

Leo
Leo

Reputation: 3143

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.

Upvotes: 2

Joe Smith
Joe Smith

Reputation: 1920

I think it is timing. You tried to print shortName right after presenting the alert. At that time the value is not set yet.

You can either use semaphore to wait till it is set or do whatever you want to do in the action closure for "submit".

Upvotes: 0

Related Questions