Running methods inside a block in Swift - swift

This is probably a dumb question, but still... I'm calling a function inside a block like this:
let makeRocks = SKAction.sequence([SKAction.runBlock(self.createMyNode),<---- here should be ()
SKAction.waitForDuration(0.1, withRange: 0.15)])
func createMyNode() {
// blabla
}
I don't get it. There should be parentheses after self.createMyNode but this still compiles. How is that so?

You're not in fact calling the function, createMyNode will be called inside SKAction.runBlock, you're simply passing it as an argument.
Take a look at the type SKAction.runBlock accepts, from the SKAction documentation:
class func runBlock(_ block: dispatch_block_t) -> SKAction
And from the GCD documentation:
typealias dispatch_block_t = () -> Void
Therefore, SKAction.runBlock accepts a function (or closure, they're the same thing), which takes no arguments and returns Void; which is exactly what you're suppling with createMyNode.
With this information it's clear to see why you don't add parentheses after createMyNode - because that would call the function, thus passing Void (the return type of createMyNode) to SKAction.runBlock, which SKAction.runBlock won't accept.
To clarify, here's another example. Say you had the function:
func takesAFunc(c: (Int, Int) -> Int) -> Void {
print(c(1, 2))
}
And you wanted to pass in a function that added the two numbers. You could write:
takesAFunc { num1, num2 in
num1 + num2
}
// Prints: 3
But alternatively, you could just pass in the + operator that accepts Ints - that's a function too. Take a look at the definition:
func +(lhs: Int, rhs: Int) -> Int
That matches the type required by takesAFunc, therefore you can write:
takesAFunc(+) // Prints: 3

runBlock wants a function as parameter which you provide here (so self.createMyNode is only a reference to the function itself).
But you can also wrap the function call in a closure like so:
let makeRocks =
SKAction.sequence([SKAction.runBlock{ self.createMyNode() },
SKAction.waitForDuration(0.1, withRange: 0.15)])

Related

Store a Swift function and its parameter values and call it later

There are multiple functions in my app, where each have a different number of parameters
func functionOne(foo: Foo, bar: Bar)
func functionTwo(foo: Foo, bar: Bar, baz: Baz, quux: Quux)
func functionThree(foo: Foo)
The parameter values can vary.
My requirement is to press a button which will run whichever function of the above was run most recently, including its parameter values.
Storing the whole thing (function and parameters) in a variable did not work.
A function and its parameters are stored in a closure. For example:
func f(_ x: Int) {}
func g(_ x: Int, _ y: Int) {}
var saved: () -> Void = { f(1) }
saved() // this executes f(1)
saved = { g(2, 3) }
saved() // now this executes g(2, 3)
You can use #escaping and #autoclosure to store a function and its parameters as a closure in a property of your class and then call it.
Add this class to your project:
// Stored Function Class
class SFC {
static var calledFunc: (() -> Void)?
static func call(_ function: #escaping #autoclosure () -> Void) {
// Store the function
calledFunc = function
// Call it
function()
}
static func reCall() {
// Called the stored function
calledFunc?()
}
// Call this when you no longer want SFC to hold onto your function.
// Your class will not deallocate if you passed in `self` to `call()`
// as long as `calledFunc` retains your function. Setting it to `nil`
// frees it.
static func forget() {
calledFunc = nil
}
}
This is how you use it:
Wrap any function call that you want to repeat with SFC.call(). Call SFC.reCall() to call that function again.
Example:
func add(_ a: Int, _ b: Int) {
print("\(a) + \(b) = \(a + b)")
}
SFC.call(print("hello", "bye"))
SFC.reCall()
SFC.reCall()
SFC.call(add(2, 3))
SFC.reCall()
Output:
hello bye
hello bye
hello bye
2 + 3 = 5
2 + 3 = 5
How does this work?
The contents of the call to call() are automatically wrapped in a closure (that is what #autoclosure does) and passed as function. The #escaping means that you'll be hanging onto that closure after call() returns.
That closure is then assigned to the calledFunc property so that it can be called again later from reCall().
Note: If the function you are passing to call() is a member function, you'll need to explicitly specify self. For example: SFC.call(self.functionThree(foo: fooVar)). Be sure to call SFC.forget() when it's time for your class to be freed so that SFC doesn't hold onto your class instance.

Why don't value types require #escaping or explicit self as opposed to escaping closures?

So this code is is an escaping closure and I do understand that it's #escaping is required because the function escapes and appends or changes completion handlers.
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: #escaping () -> Void) {
completionHandlers.append(completionHandler)
}
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200"
completionHandlers.first?()
print(instance.x)
// Prints "100”
This simple code however doesn't require the value type to be marked as escaped even though it changed the variable x.
var x: Int = 0
func x (y: Int) {
x += y
}
x (y: 7)
print (x)
This confuses me because I don't understand why in the second code self can be assessed implicitly, but with an escaping closure self is required (if it were called).
I do understand that it's #escaping is required because the function escapes and appends or changes completion handlers.
It's not entirely clear from that phrase that you understand what #escaping means. It means that this function parameter gets stored rather than executed immediately and thrown away.
That is what happens in your first example: we are handed a () -> Void and instead of merely executing it, we append it to a persistent array.
In your second example, there is no function parameter (just a lowly Int) so the matter never arises.
The reason why the question arises for a function parameter is that functions are closures, so when a function gets stored, other stuff from its environment can get stored. That can have unintended consequences, so you have to acknowledge that you're aware of this by saying #escaping.

Adding vars to a closure swift

hey I'm a little confused about block syntax. I currently have a function defined like so:
func presentRateAlert(ID: Int, didDismiss: (() -> Void)?)
Currently I do not have any parameters in the block, but I would like to include two. rating: Double? and message: String?. How would I include these?
In your function declaration, didDismiss is a closure. It's type is (() -> Void)?), which is an Optional closure that takes no parameters, and returns Void (no result.)
If you change it to (() -> (Double,String)?
Then your closure returns a Tuple which contains a Double and a String.
(In Swift a function can only return one result. Normally you make that result a Tuple when you want to return more than one thing.)
EDIT:
Based on your edits, it seems you want to add PARAMETERS to your closure, not a return value as you said originally.
An Optional closure that takes a Double and a String and does not return a value would be declared as ((Double, String) -> Void)?)
A function that takes such a closure might look like this:
func test(id: Int, closure: ((Double, String) -> Void)?) {
closure?(3.14, "pi")
}
And calling it might look like this:
test(id: 6, closure: {
(aDouble, aString) in
print("In closure, double = \(aDouble), string = \(aString)")
})

Accessing number of parameters in a closure in Swift

Suppose I have a function:
func test(closure: (closureArgs: Double ...) -> Double){
//some logic
}
Then later, I call it with:
test({$0 + $1 + $2 + $3})
Is it possible to get the number of closureArgs provided within test? The goal would be to do overloading. For example, test could include some code like:
func test(closure: (closureArgs: Double ...) -> Double){
//somehow get access to number of arguments in closureArgs within the closure that was passed.
}
To clarify - I mean I need to access closureArgs's length INSIDE test but OUTSIDE closure
Is it possible to get the number of closureArgs provided within test?
The Short Answer
No.
Slightly Longer Answer
No, it is not. Here's why:
The function is taking a closure as it's argument that by definition takes a variadic number of arguments. There's no possible way for someone calling the function to designate how many arguments the closure should take ahead of time. For example, if I were to call your function, it might look like this:
test() { (closureArgs: Double...) -> Double in
var n: Double = 0
for i in closureArgs {
n += i
}
return n
}
As you'll notice, I don't define the number of arguments anywhere because the number of arguments is only specified when the closure is called. Then the number can be determined inside, or possibly returned.
Basically, the closure is called within test, so only you the caller know how many arguments it takes. Anyone consuming this function has no control over it.
The only way I can think of is to have the closure return a tuple that contains the number of arguments and a function that gives the answer, like this:
func test(c: (Double...) -> (Int, (Double...) -> Double)) {
let (argCount, function): (Int, (Double...) -> Double) = { c($0) }()
switch argCount {
// do something with function here
}
}
func sum(a: Double...) -> (Int, ((Double...) -> Double)) {
return (a.count, { reduce(a, 0, +) })
}
Something like that might work, but I'm not in a place where I can test it.
Edit: I'm trying to test this now, and it's close, but it doesn't work yet...
Edit: Okay, this works, but maybe not in the way that you want...
func test(c: (Int, Double)) {
let (argCount, result) = c
switch argCount {
case 2:
println("2 args were passed")
println("The result was \(result)")
default:
println("nothing")
}
}
func sum(a: Double...) -> (Int, Double) {
return (a.count, reduce(a, 0, +))
}
Now test(sum(2, 4)) will print that the number of arguments was 2 and the result was 6.
The thing is, when you are passing a closure that already has arguments supplied (and it needs arguments to know how to calculate the count) then you're closure function already evaluates to a result. So have the closure return the number of arguments that it used to calculate the result along with the result. Then in test you can work with both the number of arguments and the result.
I don't know...it's hard to know exactly what you are after because I'm not sure what kind of logic you need to implement once you know the number of arguments...
Edit: Sorry I keep going on and on, but it seems like you know how many arguments are going to be included when you call test, right? I mean, in your example you supplied 4 arguments:
test({$0 + $1 + $2 + $3})
(Although, you really need to rewrite that as:
test({ return $0[0] + $0[1] + $0[2] + $0[3] })
...cuz remember, variadic parameters are passed as an array...)
So if you know how many arguments are going to be in the closure when you pass it to test, just include the number of arguments as a parameter in test, like this:
func test(count: Int, closure: (Double...) -> Double) {
switch count {
case 1:
// do what you want if there is only one argument
case 2:
// do what you want if there are two arguments...etc.
}
}
Now when you call test, you just pass the number of arguments as an Int:
test(4, { return $0[0] + $0[1] + $0[2] + $0[3] })
In other words, you always know how many arguments you are passing to the closure when you pass it. If you want test to know, just include that as a parameter.
The answer goes back to how Swift passes arguments to varargs functions, which is as an array. Generally speaking, the function definition:
func takesVarArgs(args: Double...)
Is syntactic sugar, providing for simpler invocation, for the declaration:
func takesVarArgs(args:[Double])
So, in your case, your closure will be invoked as:
func test(closure: (closureArgs:[Double]) -> Double)) -> Double
Then, within your closure you could get the number of arguments with:
closureArgs.count

Swift curried function behaves differently from expanded version

I have a curried function in Swift:
func counter(var val: Int)() -> () {
val++
println(val)
}
According to this answer it should be equivalent to this:
func counter(var val: Int) -> (() -> ()) {
func curryFunc() {
val++
println(val)
}
return curryFunc
}
However, when I run the following code:
let x = counter(3)
x()
x()
with the first one, I get 4, 4; whereas with the second one, I get 4, 5.
I am using the release Xcode 6.0.1.
The difference is that in the first version the body of the curried function is a normal function implementation, whereas in the 2nd case there's a closure. As stated in the documentation:
Closures can capture and store references to any constants and variables from the context in which they are defined.
In your case, val is captured, and retained among consecutive calls.
Addendum - if you want to have your 2nd function to behave like the curried one, you should store the parameter in a variable declared inside the function body:
func counter(val: Int) -> (() -> ()) {
func curryFunc() {
var unretainedVal = val
unretainedVal++
println(unretainedVal)
}
return curryFunc
}
The captured value val doesn't change, so the function keeps a reference to its original value.