0

I've read a few examples on declaring handlers for UIAlertViews and somehow I just can't grasp the concept of the proper syntax. I've seen a few examples where they do one of the following:
- handler: someFunction
- handler: {action in SomeFunction} (what does "action in" mean?) - handler: { _ in print("Foo!") (again, what does "in" mean?)

My biggest concern is that I don't know what these things mean. and I'm trying to use the first style however I get the following error: "Variable used within its own initial value"

let answerVCAlert = UIAlertController(title: "Your turn", message: "What's the answer?", preferredStyle: .alert)
    let submitAnswer = UIAlertAction(title: "Submit", style: .default, handler: submitAnswer(answer: " ")) //grab from textfield

    let noAnswer = UIAlertAction(title: "No Answer", style: .default, handler: submitAnswer(answer: " "))

    func submitAnswer(answer: String) {
        print ("The string passed is \(answer)")
        //compare answer to correct answer
    }

    func attemptAnswer() {
        answerVCAlert.addAction(submitAnswer)
        answerVCAlert.addAction(noAnswer)
        //answerVCAlert.addTextField //how ??? too many different examples

        self.present(answerVCAlert, animated: true, completion: nil)
    }
rmaddy
  • 314,917
  • 42
  • 532
  • 579
dvd.Void
  • 339
  • 1
  • 5
  • 21
  • where are you calling the attempAnswer method? – Reinier Melian Nov 26 '17 at 12:19
  • 2
    *"I don't know what these things mean"* – You'll want to read the [Closures](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html) chapter in the Swift reference. – Martin R Nov 26 '17 at 12:24
  • I have read closures, I know the concept of what a closure is and am also familiar with lambda expressions in Java. What usually throws me off is part of the syntax (especially when using words like "action" or "in", like where did you define the action or what (and why?) do you mean in?). Sorry if it was unclear in my OP, I know what the concepts are but the syntax is that gets me since everyone just gives examples that have this syntax I'm not familiar with – dvd.Void Nov 26 '17 at 14:02

1 Answers1

1

As mentioned in the comments, now's the time to learn how to using closures or completion handlers. It's time well spent.

Here's some working code (based on your's but with some minor changes) that also includes a textfield. A good Swift 3 example of getting the text from an alert textfield is this SO answer. There is a change in Swift 4 syntax in my code below.

I've indented the code in hopes it helps you understand completion handlers better. I added some inline comments also.

Here's the alert:

// I changed the name of your alert controller for brevity

let alertVC = UIAlertController(
    title: "Your turn",
    message: "What's the answer?",
    preferredStyle: .alert)

// Add a textfield called answerText. You may not want the placeholder to be blank.

alertVC.addTextField(configurationHandler: {(answerText: UITextField!) in
    answerText.placeholder = "Default answer"
})

// Add a Submit button that will call submitAnswer()

let submitAnswer = UIAlertAction(
    title: "Submit",
    style: .default,
    handler: { action -> Void in
        self.submitAnswer(alertVC.textFields![0])
    })
alertVC.addAction(submitAnswer)

// Add a No Answer button that will call noAnswer()
// NOTE: I changed this to be style of cancel... check out how it's rendered.

let noAnswer = UIAlertAction(
    title: "No Answer",
    style: .cancel,
    handler: { action -> Void in
        self.noAnswer()
    })
alertVC.addAction(noAnswer)

// I think you *want* everybody to try to answer, so let's make that the preferred action.

alertVC.preferredAction = submitAnswer
present(
    alertVC,
    animated: true,
    completion: nil)

And here's the results:

func submitAnswer(_ answer: String) {
    print ("The answer is \(answer)")
    //compare answer to correct answer
}
func noAnswer() {
    print ("Cancel was tapped.")
}

Among the changes I made are:

  • Changed the style of one action from .default to .cancel to give you an idea of what that does.
  • Added self to the completion handler calls - they are required.
  • Changed the signature of submitAnswer() to no longer need the parameter label. It's Swiftier that way.
  • Changed the noAnswer action call from submitAnswer() to noAnswer() to distinguish what the user tapped on.
  • Hi, thank you for the code. It really helps to break it down like that. I have just a question, why or what is "action -> Void in". Where can I read exactly what each of those 4 things mean. I assume -> Void means it returns nothing. But the "action" and "in" are really puzzling me. Where are these defined? are they exact words or are they variables? can I replace those words with something else? – dvd.Void Nov 26 '17 at 14:07
  • That's part of understanding closures or completion handlers. The link @Martin_R gave you along with the one I did should help. In my link scroll down to the completion handler section. I just deleted my own explanation of the `action -> Void in` because I'm no expert on this. Most times my code doesn't need a handler (I just use `nil`) and those times I do I work with that link I gave you. It's very powerful (and odd) syntax - you're really passing a function as a parameter to the alert controller - and I'm still gaining an understanding of it! –  Nov 26 '17 at 14:31