2017-10-11 44 views
0

我尝试用管理器管理我的功能。问题是功能代码更新并且在我将该功能添加到我的管理器的那一刻不会保存。我尝试用这个例子来解释我的问题:功能数组不会保留其创建的值

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 
    } 
} 

那么我这样做:

let queueManager = QueueManger() 

var value = 1 

queueManager.add("simpleFunction"){ 
    print(value) 
} 

value = 2 

queueManager.add("simpleFunction"){ 
    print(value) 
} 

queueManager.runFist() 
queueManager.runFist() 

,其结果是:

2 // Because value is 2 in both functions. But i added the function while value was 1?? 
2 

但我想要的结果:

1 
2 

我在做什么错?提前致谢!

编辑:很容易操场例如:

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 

编辑2: 我知道2 2是我的代码正确的输出。但是我想把它的功能保持在创作状态。这是否有可能?

编辑3: 非常感谢您的帮助。但我认为我没有足够的解释我的问题来得到答案。我想在稍后调用一个带有参数的函数。我不想保留对参数值的引用。我只需要用这些参数值调用函数。

回答

1

为了了解这里发生的事情让我们来看看一步一步:

  1. 分配1到值
  2. 打印指令添加到QueueManager
  3. 分配2值
  4. 将打印指令添加到QueueManager
  5. 使用运行功能runFirst()

当您添加print(value)指令时,您将通过value作为参考类型。这在变量functionsvalue之间产生了强烈的参考。因此,当您实际执行这些指令时,使用runFirst()它会使用在该时间点存储在value中的值。

让我们探索利用这个例子:

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 

在这种情况下,我们执行runFirst()先更新值。因此输出是5 5

TL; DR - 通过参考传递导致函数打印变量value的当前值。

编辑:将数据绑定到QueueManager中的函数,这将确保数据的当前值(在函数定义期间)与该函数关联。

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 
+0

是否可以将该功能保持在创建状态?我想在稍后用它添加它时的价值来调用它。 –

+0

当然,你需要做的就是确保你的价值传递。我用最简单的方法更新了答案。 – NSAdi

+0

感谢您的回答!但这似乎是一个非常肮脏的解决方案。我用这个管理了100多个功能。如果我将为每个函数创建新的变量,我将创建超过1000个新值。必须有其他方法来存档。其他语言也可能。 –

1

基于您的代码,显然结果应该是:

2 
2 

,因为你以后编辑value = 2

还呼吁queueManager.runFirst()拖时间,如果add功能应包括functions.append((funcName, function))那么我认为其function参数应为@escaping如下:

class QueueManager { 
    typealias FunctionType =() ->() 

    private var functions = [(String, FunctionType)]() 

    func add(funcName: String, function: @escaping 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 
    } 
} 

这样的输出:

let queueManager = QueueManager() 

var value = 1 

queueManager.add(funcName: "simpleFunction") { 
    print(value) 
} 

queueManager.runFirst() 

value = 2 

queueManager.add(funcName: "simpleFunction"){ 
    print(value) 
} 

queueManager.runFirst() 

应该是:

1 
2 

因为-simply-我叫queueManager.runFirst()之前调用value = 2

同样的问题也适用于您简单的例子:

var str = "1" 
func go() { 
    print(str) 
} 

var array:[()->()] = [] 
array.append(go) 
array[0]() 

str = "2" 

array.append(go) 
array[1]() 

致电array.append(go)不会导致执行go(),您应该致电array[0]();由于您正在尝试打印相同的变量(str)的值,因此它将打印最新值为always。如果要为每个功能单独保存每个值,则应该 - 某种情况 - 申报多个变量(valuestr)。

+0

我知道问题所在。但是我想稍后调用这些函数。但我的问题是:我如何保持第一个函数的第一个值?我想用创建时间的值来存储函数。当我添加它时,它应该保持这个值的状态。如果我只是把它叫做你所做的职位,那么经理就完全没用。 –

1
import UIKit 

var str = "Hello, playground" 

class QueueManager { 

    typealias FunctionType =() ->() 

    private var functions = [(String, FunctionType)]() 

    func add(funcName: String, function: @escaping FunctionType) -> QueueManager { 
     functions.append((funcName, function)) 
     return self 
    } 

    func runFirst() -> Bool { 
     guard functions.isEmpty == false else { return false } 
     print(functions) 
     functions.first!.1() 
     functions.removeFirst() 
     return true 
    } 
} 

var value = 1 
let queueManager = QueueManager() 

func simpleFunction(_ value: AnyObject){ 
    print(value) 
} 

queueManager.add(funcName: "simpleFunction"){ 
    simpleFunction(value as AnyObject) 
} 

queueManager.add(funcName: "simpleFunction"){ 
    value = 2 
    simpleFunction(value as AnyObject) 
} 

queueManager.runFirst() 
queueManager.runFirst() 

你必须加入第一simpleFunction后更新你的价值。

游乐场输出:

[( “simpleFunction”(功能)),( “simpleFunction”(功能))]

[( “simpleFunction”(功能) )]

+0

感谢您的回答。可悲的价值在其他地方改变了。我无法在函数中更新它。我只需要在添加函数的时候保持价值 –