ref – http://stackoverflow.com/questions/36749231/function-produces-expected-type-string-did-you-mean-to-call-it-with
There are two ways to assign closure to variable
First way, is very forward. You create a variable to be of type closure. This closure, let’s say, takes no parameter, and returns a String.
You assign it that variable and define the closure implementation. Then you execute the closure with “()”.
1 2 3 4 5 6 7 |
// variable take on a closure // a closure that has no parameters and return a String var hello: () -> (String) = { return "Hello!" } print(hello()) |
Second way, is a bit different. You define the closure definition, then call it in one move by using the “()”. Then you assign the resulting value to the variable hello2. Just make sure the variable type and the closure definition’s return type matches.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// That is not a computed property. // You are initializing your variable hello2 to the return result of the closure // The parentheses make that happen; that is how you call a function. /* var hello2: String = { return "Hello!" } */ // Thus you define the closure and execute it, all in one move // Then assign the result as the initial value of hello2. var hello2: String = { return "Hello2!" }() print(hello2) |
Defined as part of a class, using self
In a class, when you assign a closure to a property variable, you may want to use self in the closure implementation.
1) Use lazy – This is because as part of the process of the class initialization, self is not ready yet, thus, if you were to create a property, and define a closure
definition, you cannot use self. The only way to use self, is if you apply lazy to indicate that the property will be executed later in time when it is ready to be used, and this definitely happens after the initialization. This means that self is ready, and thus you can use it. Note that lazy means the closure is defined and assigned at a later time after when it needs to be used.
2) Usage of self – When you use self, you can use unowned or weak. Weak means it is optional, and thus, you must use the ? symbol to apply chaining access if you want to use its properties. When its unowned, it means its non-optional. Thus, you can just access as is.
3) Closure variable type – you must specify the closure’s type right after the variable, then assign it to the closure definition, like so:
1 2 3 |
public lazy var hello : () -> () = { [weak self] in self?.name = "Ricky Tsao" } |
You now have a variable of closure type, and can be executed multiple times later simply by using “()” after the closure variable name.
Execute Once
You can also declare a normal variable with a type, and take on the result of a closure once. In this case, you must define the closure definition and
execute it by using “()” in one step. Then you have it return the result back to the variable.
1 2 3 4 5 6 |
public lazy var hello2: String = { [unowned self] (a: String, b: String) -> String in self.name = "haha" return a + ", " + b }("Ricky", "Tsao") |
Notice the parameter list of the closure. If you want to add a self to use in the closure definition, just use brackets around your weak/unowned self
and put it in front of the closure parameters.
If you have parameters, make sure you pass them in.
Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
class Test { var name : String = "" // Thus you define the function and call it, all in one move, and assign the result as the initial value of test. // weak means it is optional, can point to nil, and will be zero-ed out // unowned means it is non-optional, may result in dangling pointer (points to address with garbage content) public lazy var hello2: String = { [unowned self] (a: String, b: String) -> String in self.name = "haha" return a + ", " + b }("Ricky", "Tsao") //define closure // weak means it is optional, can point to nil, and will be zero-ed out // thus, when you want to access properties of the weak self, make sure you use '?' to apply optional chaining // another way is to straight up use force unbinding, then access its property from its data. public lazy var hello : () -> () = { [weak self] in self?.name = "Ricky Tsao" } } |
Usage:
1 2 3 |
var myTest = Test() myTest.hello() print(myTest.hello2) |