Passing functions as parameters in Swift
Just in case anyone else stumbles upon this. I worked out an updated simple solution for Swift 5.1 while I was working through this for while building a global alert utility for a project.
Swift 5.1
Function with Closure:
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()
}
}
}
Function Called:
showSheetAlertWithOneAction(messageText: "Here's a message", dismissButtonText: "Nope", actionButtonText: "Okay", presentingView: self.view.window!) {
someFunction()
}
Adding to got2jam's answer... If you're working with UIAlertController
The generic function to show an alert with closure:
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)
}
Now you can call it like that:
showAlertAction(title: "This is the title", message: "This is the message") {
self.close()
}
in this case, close is the particular UIAlertAction to execute
func close(){
dismiss(animated: true, completion: nil)
}
Oneword answer for your question is Closures
The Default Syntax for closures is () -> ()
Instead of Selector you could directly mention the method definition
func showConfirmBox(msg:String, title:String,
firstBtnStr:String, firstSelector:(sampleParameter: String) -> returntype,
secondBtnStr:String, secondSelector:() -> returntype,
caller:UIViewController) {
//Your Code
}
But using this will create readability problems so i suggest you to use 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()
}
You can call your method like this
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
}
}