51

I am attempting pass a function to another function and then have the passed function executed passing to it a variable.

Here is my code:

func showStandardPrompt(prompt:String,view: UIViewController,numberInput: Bool, callback: (()->(String))?) {
    let alert = UIAlertController(title: "Input Data", message: prompt, preferredStyle: .Alert)
    alert.addTextFieldWithConfigurationHandler { (textField) in
        if numberInput {
            textField.keyboardType = .NumberPad
        }
    }

    let OKAction = UIAlertAction(title: "OK", style: .Default) { (action) in
        let field = alert.textFields![0] as UITextField
        callback?(field.text!)
    }

    alert.addAction(OKAction)
    let CancelAction = UIAlertAction(title: "Cancel", style: .Default, handler: nil)
    alert.addAction(CancelAction)
    view.presentViewController(alert,animated: true, completion: nil)
}

The error I get is in

callback?(field.text!)

The error is "Cannot convert value type of 'String' to expected argument type '()'. I know it's a matter of syntax - just don't know what it should be.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
Floyd Resler
  • 1,786
  • 3
  • 22
  • 41
  • Please try to indent your code properly, because it's difficult to understand otherwise. I fixed it for you this time. – rob mayoff Oct 22 '15 at 21:01

5 Answers5

127

Rob's answer is correct, though I'd like to share an example of a simple working callback / completion handler, you can download an example project below and experiment with the getBoolValue's input.

Swift 5:

func getBoolValue(number : Int, completion: (Bool)->()) {
    if number > 5 {
        completion(true)
    } else {
        completion(false)
    }
}

getBoolValue(number: 2) { (result) -> () in
    // do stuff with the result
    print(result)
}

Important to understand:

(String)->() // takes a String returns void
()->(String) // takes void returns a String
multitudes
  • 2,898
  • 2
  • 22
  • 29
Dan Beaulieu
  • 19,406
  • 19
  • 101
  • 135
  • That is not a playground. – Price Ringo Oct 22 '15 at 21:37
  • 1
    @PriceRingo thanks, I thought I uploaded a playground. It was a while ago – Dan Beaulieu Oct 22 '15 at 21:38
  • 1
    `completion(result: number>5)` ? – GoZoner Oct 23 '15 at 04:13
  • Thanks for the example. That' exactly what I needed to make my project work! And, for me, this is so much better than the old way of UIAlertView where I had to set a tag and then check the button index and tag in the delegate method. – Floyd Resler Oct 23 '15 at 12:52
  • Not a problem. This exact example is what made callbacks clear to me. – Dan Beaulieu Oct 23 '15 at 12:54
  • Great, just what I need, in swift 4 the changes are a little bit different: in the parameters should be `func getBoolValue(number : Int, completion: @escaping (_ result: Bool)->()) {...}` and to set value should be `completion(true)` . I hope this clarification will be useful to you. – iGhost May 09 '19 at 04:29
  • 2
    this gonna be *Function types cannot have argument labels; use '_' before 'result' *error – Zaporozhchenko Oleksandr Aug 28 '19 at 11:28
24

I use this way :

ViewController1

destination.callback = { (id) -> Void in
            print("callback")
            print(id)
        }

ViewController2

var callback: ((_ id: Int) -> Void)?
callback?(example_id)
Álvaro Agüero
  • 4,494
  • 1
  • 42
  • 39
16

try below code updated for Swift 3

func getBoolValue(number : Int, completion: (Bool)->()) {
    if number > 5 {
        completion(true)
    } else {
        completion(false)
    }
}

getBoolValue(number : 8, completion:{ result in
    print(result)
})
Anand Verma
  • 572
  • 1
  • 6
  • 11
7

You've declared callback to take no arguments, and then you're trying to pass it an argument.

You specified type (()->(String))?, which is an optional function that takes no arguments and returns a String.

Perhaps you mean to specify ((String)->())?, which is an optional function that takes a String and returns nothing.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
2

In the parameters for showStandardPrompt, you declare callback to have the type ()->(String), which is a function which takes no parameters and returns a String.

You then call it with field.text! as a parameter, which obviously conflicts with the previously given type.

You need to correct the type given to callback to take a String argument and return nothing:

(String)->()
stonesam92
  • 4,307
  • 2
  • 19
  • 24