Передача функций в параметрах Swift

У меня есть следующая функция, работающая, как я ожидаю, в iOS 8:

func showConfirmBox(msg:String, title:String,
    firstBtnStr:String,
    secondBtnStr:String,
    caller:UIViewController) {
        let userPopUp = UIAlertController(title:title,
            message:msg, preferredStyle:UIAlertControllerStyle.Alert)
        userPopUp.addAction(UIAlertAction(title:firstBtnStr, style:UIAlertActionStyle.Default,
            handler:{action in}))
        userPopUp.addAction(UIAlertAction(title:secondBtnStr, style:UIAlertActionStyle.Default,
            handler:{action in}))
        caller.presentViewController(userPopUp, animated: true, completion: nil)
}

Я хотел бы сделать что-то вроде следующего, чтобы передать в качестве аргумента методы, которые будут выполняться, когда одна или другая из кнопок будет затронута:

func showConfirmBox(msg:String, title:String,
    firstBtnStr:String, firstSelector:Selector,
    secondBtnStr:String, secondSelector:Selector,
    caller:UIViewController) {
        let userPopUp = UIAlertController(title:title,
            message:msg, preferredStyle:UIAlertControllerStyle.Alert)
        userPopUp.addAction(UIAlertAction(title:firstBtnStr, style:UIAlertActionStyle.Default,
            handler:{action in caller.firstSelector()}))
        userPopUp.addAction(UIAlertAction(title:secondBtnStr, style:UIAlertActionStyle.Default,
            handler:{action in caller.secondSelector()}))
        caller.presentViewController(userPopUp, animated: true, completion: nil)
}

Очевидно, что я не делаю правильные вещи с firstSelector и secondSelector, потому что то, что я пробовал до сих пор, не работает. Я полагаю, что я не использую правильный синтаксис для того, что хочу, но я уверен, что можно сделать то, что я хотел бы сделать. Любая идея о том, как правильно это сделать?

Ответ 1

Ответ на однополярный ответ на ваш вопрос: Закрытие

Синтаксис по умолчанию для замыканий - () ->()

Вместо Selector вы можете непосредственно указать метод defnition

func showConfirmBox(msg:String, title:String,
    firstBtnStr:String, firstSelector:(sampleParameter: String) -> returntype,
    secondBtnStr:String, secondSelector:() -> returntype,
    caller:UIViewController) {
    //Your Code
}

Но использование этого приведет к созданию читаемых проблем, поэтому я предлагаю вам использовать typeAlias

typealias MethodHandler1 = (sampleParameter : String)  -> Void
typealias MethodHandler2 = ()  -> Void

func showConfirmBox(msg:String, title:String,
                    firstBtnStr:String, firstSelector:MethodHandler1,
                    secondBtnStr:String, secondSelector:MethodHandler2) {

    // After any asynchronous call
    // Call any of your closures based on your logic like this
    firstSelector("FirstButtonString")
    secondSelector()
}

Вы можете вызвать свой метод следующим образом

func anyMethod() {
   //Some other logic 

   showConfirmBox(msg: "msg", title: "title", firstBtnStr: "btnString", 
         firstSelector: { (firstSelectorString) in
              print(firstSelectorString) //this prints FirstButtonString
         }, 
         secondBtnStr: "btnstring") { 
           //Invocation comes here after secondSelector is called

         }
}

Ответ 2

Я написал эту процедуру на основе различных примеров сайтов. Вот как я называю рутину...

@IBAction func buttonClick(_ sender: Any) {
    SS_Alert.createAlert(parmTitle: "Choose", parmMessage: "Please select Yes or No", parmOptions: ["Yes","No","Cancel"], parmFunctions: [testYes, testNo, nil])
}

func testYes() {
    print("yes")
}

func testNo() {
    print("no")
}

Вы можете передать параметры кнопок и функции, которые будут выполняться при выборе кнопок. Потребовалось немного времени, чтобы понять, как передавать функции в качестве параметров, но, похоже, сейчас работает нормально. Я столкнулся с какой-то странной проблемой, пытающейся использовать циклы для динамического добавления кнопок, и, наконец, сдался и использовал переключатель /case. Я включил код цикла, который я пытался использовать, если кто-то может понять, что я делаю неправильно, дайте мне знать. Благодарю.

https://github.com/blakeguitar/iOS/blob/0e243d13cb2decd6e1dbe134a8a046c2caed3876/SS_Alert.swift