How to define a function with a function type parameter in Swift - swift

I could define a function like this
func doWithAction(action: ()-> void) {
// something
}
However, when I use the function, the auto-completion of Xcode give me a block/closure
self.addPullToRefreshControllerWithAction { () -> void in
}
I know closure and function are something same in Swift, but I want to lead the one who use this function to pass a function in, not a block. The reason why I do this is I want this function to behave like a selector and a delegation

yes, closure and functions are practically the same in swift, so if the function expects a closure, you can pass a function with the same signature as a parameter instead. like this
func iAmAFunc(() -> Void) -> Void {
//do stuff
}
func funcThatTakesVoidAndReturnsVoid() -> Void {
//do stuff
}
var closureThatTakesVoidAndReturnsVoid: () -> Void = { }
iAmAFunc(funcThatTakesVoidAndReturnsVoid)
iAmAFunc(closureThatTakesVoidAndReturnsVoid)

Related

How to call a parameter label of type closure (Swift)

Closures As Parameters
let driving = {
print("I'm driving in my car.")
}
func travel(action: () -> Void) {
print("I'm getting ready to go.")
action()
print("I arrived!")
}
travel(action: driving)
action is a parameter label. How come we consider it as a function call as in action()?
Lets look at a brief example:
func myFunction() {...} Swift sees this as () -> Void
the same way that Swift sees this "John" as String
So when you write a function like myFunction you could really say
func myFunction() -> Void {...} for the same result.
Now action is defined as a parameter as a function but the type that it accepts for that parameter is () -> Void aka a closure which for now you can think of just another function.
So the line action() is just the call of that function.
But be sure to read up on functions accepted as parameters

How can i make protocol implementation as argument of function

How do i create Protocol as an argument of function.
In Android java, we can make an argument of interface like this.
Button.setOnClickListener(new View.OnClicklistener()
{
#Override
public void onClick(View v)
{
}
});
But how do i do same thing in Swift.
For example, i have following Protocol, how can i pass protocol while constructing it.
protocol ButtonListener
{
func onClick()
}
It seems that there is a misunderstanding for what you should use to achieve it. Probably you want to pass a closure as a parameter to the function.
Citing from the Swift programming language - Closures:
Closures are self-contained blocks of functionality that can be passed
around and used in your code. Closures in Swift are similar to blocks
in C and Objective-C and to lambdas in other programming languages.
Example:
protocol Foo {
func myFunc(onClick: (_ myView: UIView) -> Void)
}
class MyClass: Foo {
func myFunc(onClick: (UIView) -> Void) {
// ...
}
}
Here we have a Foo protocol contains myFunc which has a closure parameter of type (UIView) -> Void.
Therefore:
let object = MyClass()
object.myFunc { view in
// you can access `view` here as:
view.backgroundColor = ...
view.frame = ...
}
In Swift, these single-method protocols, as event handlers are not necessary. In Swift, you can create any kind of closure type you want.
Your onClick method can be represented by the closure type () -> Void (accepts no parameters and returns Void). Instead of setOnClickListener as a method, you can just declare onClick as a property:
var onClick: (() -> Void)?
And then you can set it just like you would with any other property:
onClick = {
print("I am clicked!")
}
To call onClick, you can unwrap it first to make sure it's not nil:
if let onClick = self.onClick {
onClick()
}
// or
onClick?()
If you are familiar Java 8, closure types are kind of like functional interfaces, except you get more freedom with closure types. Consumer<String> would correspond to (String) -> Void, Function<String, Integer> would correspond to (String) -> Int, etc.
You can give it by protocol.
protocol ButtonListener {}
extension ButtonListener where Self: UIView {
func btnClick() {
// print func
}
}

how to pass a callback function in another function in swift?

so i'm doing my first app,
and i want to do a function that will be a uniform funciton to sevral places in the system, and not belong to only one specific class.
Is there a way for me to pass a callback function as a parameter to another function ?
here is just a demonstration of what i mean.
ClassA {
func classAcallbackFunction (displayString: String) {
print (displayString)
}
ClassB().classBFunction(classAcallbackFunction())
}
ClassB {
func classBfunction (myCallbackfunc: func) {
mycallbackfunc("all is working !!!")
}
}
The parameter you have declared is not correct. Replace it with something like this:
func classBFunction(_ completion: (String) -> Void) {
completion("all working")
}
Like shared by regina_fallangi in the comments, callbacks are usually called completion handlers, which is why I replaced the names accordingly.
Extra Credit:
If you only want to optionally pass a function, you could do this:
func classBFunction(_ completion: ((String) -> Void)? = nil) {
completion?("all working")
}
Now you could also just call classBFunction().

Why assign void to local variable

So this is actually possible.
func clearItems() {
}
func reloadItems(_ clearItems: (() -> Void)? = nil) {
if let void = clearItems?() {
}
}
reloadItems(clearItems)
Should this be illegal? Or should we be forced to use _ intead of a variable name? Can void actually be consumed in some way here?
Void is a type in Swift just like anything else. There's seldom need to pass it around, but that doesn't change the fact the language supports returning and storing it in constants.
This implicitly happens anyway, you're just being explicit. You can, if you want return () at the end of every function that doesn't return a value since () represents an instance of Void. The compiler does that for you though so you don't need to.
Yes, but you need to change your reloadItems method to look like this:
func reloadItems(_ clearItems: (() -> Void)? = nil) {
if let void = clearItems {
void() // Call void.
}
}
by saying clearItems?(), you are calling the passed function, which is not the thing you wanted to do. You wanted to safely unwrap the passed function, so you need to treat it as a passed variable like the above snippet.
If you didn't use the if let statement, you can call clearItems like this:
clearItems?()
This will call the passed function if it isn't nil, and will do nothing if it is nil.
So your reloadItems function can simply become like this:
func reloadItems(_ clearItems: (() -> Void)? = nil) {
clearItems?() // This will call the passed function if it isn't nil, and will do nothing if it is nil.
}

Is there a shorthand for a function that takes no parameters and returns nothing? AKA () -> ()

The title says it all, I believe. I'm simply curious if the () -> () acting as a function's parameter...
class Test {
var isAwesome = true
func loadData (callback: () -> ()) {
callback();
}
}
... has a shorter version. That's it!
I'm not sure if there is a "Swift-way" to do it, but if you really want to shorten it:
typealias A = ()->() // alias this closure risking readability
class Test {
func loadData (callback:A) {
callback();
}
}
It is a bit of a hack I suppose.
As found in: Apple Inc. 'The Swift Programming Language'. iBooks. https://itun.es/nl/jEUH0.l
You can use the following syntax:
func someFunctionThatTakesAClosure(closure: () -> ()) {
// function body goes here
}
// here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure({
// closure's body goes here
})
// here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}
I cannot find any documentation that specifies a different solution. Every instance I can find in the current docs/book shows it how you have it. Here is a good section that talks about it. You can however call your method with some pretty short notation:
loadData {
// ...
}
Rather than having to treat it as a normal parameter:
loadData({
// ...
})
You can also call it like:
loadData() {
// ...
}
I think there is no shorter-way: I can just imagine a type-alias (like #Benzi mentioned), but the effect seems not worth the hack.
func takeEmptyFunc(emptyFunc: ()->()) { emptyFunc() }
func emptyFunc() { println("Worked"); }
takeEmptyFunc() { emptyFunc() } // prints "Worked"