Check If Variable Is a Block/Function/Callable in Swift

Check if variable is a block / function / callable in Swift

You can check the String representation of .dynamicType of the callable for existence of substring ->. Not super-elegant, but it works:

func isAClosure<T>(foo: T) -> Bool {
return String(foo.dynamicType).containsString("->")
}

var a : () -> () = { print("Foobar") }
var b : (Double) -> (Bool) = { $0 > 0 }
var c : Int = 1

isAClosure(a) // true
isAClosure(b) // true
isAClosure(c) // false

Of course, as Marcus Rossel points out in the comment above, you still wouldn't know anything about the parameters of the callable (but perhaps that could be next step to find out, given that you know it's a callable).


Addition with regard to OPs questions below: just a technical discussion, and not recommended techniques.

You use the same approach as above to check if the function argument is a closure without arguments (() -> (...)) or one with neither arguments nor return type (() -> ()), and so on. Using this approach, you can define a generic function that call the argument sent to the function only if it is of a certain closure type. For this "in-function-call", you'll have to make use of type conversion to expected closure type, much as you've described in your Q above. It'll probably be difficult to circumvent this "non-generic" approach w.r.t. calling the closures. A few examples follow below.

/* Example functions */
func isAVoidParamClosure<T>(foo: T) -> Bool {
let bar = String(foo.dynamicType).componentsSeparatedByString(" -> ")
return bar.count > 1 && (bar.first?.characters.count ?? 0) == 2
}

func callIfVoidVoidClosure<T>(foo: T) {
let bar = String(foo.dynamicType).componentsSeparatedByString(" -> ")
if bar.count > 1 && !(bar.map{ $0 == "()" }.contains(false)) {
if let foo = foo as? () -> () {
foo()
}
}
}

func isASingleDoubleReturnTypeClosure<T>(foo: T) -> Bool {
let bar = String(foo.dynamicType).componentsSeparatedByString(" -> ")
return bar.count > 1 && bar[1] == "Double"
/* rhs of '&&' lazily evaluated: [1] ok */
}

func printTwoTimesResultOfVoidDoubleClosure<T>(foo: T) {
if isAVoidParamClosure(foo) && isASingleDoubleReturnTypeClosure(foo) {
if let foo = foo as? () -> Double {
let a: Double = 2*foo()
print(a)
}
}
}

Example calls:

/* Example calls */
let a : () -> () = { print("Foobar") }
let b : (Double) -> (Bool) = { $0 > 0 }
let c : () -> Double = { 21.0 }
let d : Int = 1

isAVoidParamClosure(a) // true
isAVoidParamClosure(b) // false
isAVoidParamClosure(c) // true
isAVoidParamClosure(d) // false

callIfVoidVoidClosure(a) // Prints "Foobar"
callIfVoidVoidClosure(b)
callIfVoidVoidClosure(c)
callIfVoidVoidClosure(d)

printTwoTimesResultOfVoidDoubleClosure(a)
printTwoTimesResultOfVoidDoubleClosure(b) // Prints "42.0"
printTwoTimesResultOfVoidDoubleClosure(c)
printTwoTimesResultOfVoidDoubleClosure(d)

Can this be simplified with Lambda/Block initialization?

To solve the problem in the general case you'd need to create and then execute an anonymous function, which you can technically do as an expression:

int Foo = new Func<int>(() => 
{
int x = 0;
// Perform calculations to get x
return x;
})();

You can clean this up a bit by writing a helper function:

public static T Perform<T>(Func<T> function)
{
return function();
}

Which lets you write:

int Foo = Perform(() => 
{
int x = 0;
// Perform calculations to get x
return x;
});

While this is better than the first, I think it's pretty hard to argue that either is better than just writing a function.

In the non-general case, many specific implementations can be altered to run on a single line rather than multiple lines. Such a solution may be possible in your case, but we couldn't possibly say without knowing what it is. There will be cases where this is possible but undesirable, and cases where this may actually be preferable. Which are which is of course subjective.

Can I make #selector refer to a closure in Swift?

As @gnasher729 notes, this is not possible because selectors are just names of methods, not methods themselves. In the general case, I'd use dispatch_after here, but in this particular case, the better tool IMO is UIView.animateWithDuration, because it's exactly what that function is for, and it's very easy to tweak the transition:

UIView.animateWithDuration(0, delay: 0.5, options: [], animations: {
self.view.backgroundColor = UIColor.whiteColor()
self.view.alpha = 1.0
}, completion: nil)

Swift function can be called only once

A simple solution is to take advantage of lazy variables in the following way:

// Declare your "once-only" closure like this
private lazy var myFunction: Void = {
// Do something once
}()

...

// Then to execute it, just call
_ = myFunction

This ensures that the code inside the myFunction closure is only executed the first time that the program runs _ = myFunction


Edit: Another approach is to use so called "dispatch once tokens". This comes from Objective-C and was available in Swift until Swift 3. It is still possible to make it work, however you will need to add a little bit of custom code. You can find more information on this post -> dispatch_once after the Swift 3 GCD API changes


Edit2: Should be _ = myFunction and not _ = myFunction(), as JohnMontgomery pointed out.

Exactly what is the difference between a closure and a block ?

While a block is just a piece of code that can be composed by statements and declarations but nothing else, a closure is a real first-class object, a real variable that has a block as its value.

The main difference is that a block simply groups instructions together (for example the body of a while statement), while a closure is a variable that contains some code that can be executed.

If you have a closure usually you can pass it as a parameter to functions, currify and decurrify it, and mainly call it!

Closure c = { println 'Hello!' }
/* now you have an object that contains code */
c.call()

Of course closures are more powerful, they are variables and can be used to define custom behaviour of objects (while usually you had to use interfaces or other OOP approaches in programming).

You can think of a closure as a function that contains what that function does inside itself.

Blocks are useful because they allow scoping of variables. Usually when you define a variable inside a scope you can override the outer definitions without any problems and new definitions will exist just during the execution of block.

for (int i = 0; i < 10; ++i)
{
int t = i*2;
printf("%d\r\n", t);
}

t is defined inside the block (the body of the for statement) and will last just inside that block.

Escaping Closures in Swift

Consider this class:

class A {
var closure: (() -> Void)?
func someMethod(closure: @escaping () -> Void) {
self.closure = closure
}
}

someMethod assigns the closure passed in, to a property in the class.

Now here comes another class:

class B {
var number = 0
var a: A = A()
func anotherMethod() {
a.someMethod { self.number = 10 }
}
}

If I call anotherMethod, the closure { self.number = 10 } will be stored in the instance of A. Since self is captured in the closure, the instance of A will also hold a strong reference to it.

That's basically an example of an escaped closure!

You are probably wondering, "what? So where did the closure escaped from, and to?"

The closure escapes from the scope of the method, to the scope of the class. And it can be called later, even on another thread! This could cause problems if not handled properly.

By default, Swift doesn't allow closures to escape. You have to add @escaping to the closure type to tell the compiler "Please allow this closure to escape". If we remove @escaping:

class A {
var closure: (() -> Void)?
func someMethod(closure: () -> Void) {
}
}

and try to write self.closure = closure, it doesn't compile!

Using @discardableResult for Closures in Swift

I don't think there's a way to apply that attribute to a closure. You could capture your closure in another that discards the result:

func discardingResult<T, U>(_ f: @escaping (T) -> U) -> (T) -> Void {
return { x in _ = f(x) }
}

let g = f(5)
g(3) // warns
let h = discardingResult(g)
h(4) // doesn't warn

What's the difference between closures and callbacks in Swift?

They are two completely different, although compatible, concepts. A callback is a hook for a function to be attached to so that when an action is needed the function can be called to provide a result or affect. A closure is a function that captures local variables to be used in a scope outside of the local scope. A closure can be a callback just like any other function can be a callback but it's not limited to that use.

In your quote they are talking about how you can use a closure for the callback. In that case the compiler can infer the function signature (types of parameters and return) from the context.

Note that this has very little to do with Objective-C blocks. Swift and Objective-C are two completely different languages and blocks and closures are two different implementations of similar concepts.



Related Topics



Leave a reply



Submit