I try to manage my functions with a Manger. The problem is that the function code updates and is not saved in the moment when i add the function to my manager. I try to explain my problem with this example:
class QueueManager {
typealias FunctionType = () -> ()
private var functions = [(String, FunctionType)]()
func add(funcName: String, function: FunctionType) -> QueueManager {
functions.append(funcName, function)
return self
}
func runFirst() -> Bool {
guard functions.isEmpty == false else { return false }
functions.first!.1()
functions.removeFirst()
return true
}
}
Then i do this:
let queueManager = QueueManger()
var value = 1
queueManager.add("simpleFunction"){
print(value)
}
value = 2
queueManager.add("simpleFunction"){
print(value)
}
queueManager.runFist()
queueManager.runFist()
And the result is:
2 // Because value is 2 in both functions. But i added the function while value was 1??
2
But i want the result:
1
2
What am i doing wrong? Thanks in advance!
EDIT: Very easy playground example:
import UIKit
var str = "1"
func go() {
print(str)
}
var array:[()->()] = []
array.append(go)
str = "2"
array.append(go)
array[0]()
array[1]()
// Output:
// 2
// 2
EDIT 2: I know that 2 2 is the right output for my code. But i want to keep the function in the state of its creation. Is this somehow possible?
EDIT 3: Thanks for all of your help. But i think i`m failing to explain my problem enough to get suiting answers. I want to call a function with its parameters at a later time. I don't want to keep the reference to the parameter values. I just need to call the function with those parameter values.
In order to understand what happens here lets take a look step-by-step :
QueueManager
QueueManager
runFirst()
When you add the print(value)
instruction you pass value
as reference type. This creates a strong reference between variable functions
and value
. Hence when you actually execute those instructions, using runFirst()
it then uses the value stored in value
at that point of time.
Let's explore using this example:
var value = 5
queueManager.add(funcName: "simpleFunction"){
print(value)
}
queueManager.add(funcName: "simpleFunction"){
print(value)
}
queueManager.runFirst()
queueManager.runFirst()
value = 10
// output is 5 5
In this case we perform runFirst()
first and then update the value. Hence the output is 5 5
.
TL;DR - Pass By Reference causes function to print the current value of variable value
.
EDIT : Bind the data to the function in QueueManager
, this will make sure that the current value of data (during function definition) is associated with the function.
class QueueManager {
typealias FunctionType = (Int) -> ()
private var functions = [(String, FunctionType, Int)]()
func add(funcName: String, function: @escaping FunctionType, data: Int) -> QueueManager
{
functions.append((funcName, function, data))
return self
}
func runFirst() -> Bool
{
guard functions.isEmpty == false else { return false }
functions.first!.1(functions.first!.2)
functions.removeFirst()
return true
}
}
let queueManager = QueueManager()
// define you function within this closure
let functionClosure: (Int) -> () = { (data) in
print(data)
}
var value = 1
queueManager.add(funcName: "simpleFunction", function: functionClosure, data: value)
value = 2
queueManager.add(funcName: "simpleFunction", function: functionClosure, data: value)
queueManager.runFirst()
queueManager.runFirst()
OUTPUT :
1
2