在Swift中将函数作为参数传递

时间:2015-11-15 07:10:20

标签: ios swift function parameter-passing

我在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做正确的事情,因为我到目前为止所做的尝试都没有用。我想我没有使用正确的语法来满足我的需求,但我确信我可以做我想做的事情。知道如何正确地做到这一点吗?

4 个答案:

答案 0 :(得分:53)

您的问题的单词答案是Closures

闭包的默认语法是() -> ()

您可以直接提及方法定义

,而不是Selector
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

         }
}

答案 1 :(得分:5)

添加到 got2jam 的答案... 如果您正在使用UIAlertController

用于显示带有关闭提示的通用功能

func showAlertAction(title: String, message: String, actionClosure: @escaping () -> Void){
  let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
  alertController.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: {(action: UIAlertAction!) in actionClosure()}))
  self.present(alertController, animated: true, completion: nil)
}

现在您可以这样称呼它:

showAlertAction(title: "This is the title", message: "This is the message") {
   self.close()
}

在这种情况下, close 是要执行的特定UIAlertAction

func close(){
  dismiss(animated: true, completion: nil)
}

答案 2 :(得分:1)

我根据各种网站示例编写了这个例程。以下是我称之为常规的方法......

@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")
}

您可以传入按钮选项以及选择按钮时要执行的功能。花了一点时间弄清楚如何将函数作为参数传递,但现在似乎工作正常。我确实遇到了一个奇怪的问题,试图使用循环动态添加按钮,最后放弃并使用了一个开关/案例。我包含了我试图使用的循环代码,如果有人能弄清楚我做错了什么让我知道。感谢。

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

答案 3 :(得分:0)

以防万一其他人偶然发现这一点。在为项目构建全局警报实用程序的过程中,我为Swift 5.1设计了一个更新的简单解决方案。

Swift 5.1

带关闭功能:

func showSheetAlertWithOneAction(messageText: String, dismissButtonText: String, actionButtonText : String, presentingView : NSWindow, actionButtonClosure: @escaping () -> Void) {
        let alert = NSAlert()
        alert.messageText = messageText
        alert.addButton(withTitle: actionButtonText)
        alert.addButton(withTitle: dismissButtonText)
        alert.beginSheetModal(for: presentingView) { (response) in
            if response == .alertFirstButtonReturn {
                actionButtonClosure()
            }
        }
    }

调用的函数:

showSheetAlertWithOneAction(messageText: "Here's a message", dismissButtonText: "Nope", actionButtonText: "Okay", presentingView: self.view.window!) {
                                            someFunction()
                                }