2017-10-11 47 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

感謝您的回答。可悲的價值在其他地方改變了。我無法在函數中更新它。我只需要在添加函數的時候保持價值 –