我在SWIFT 3.0中將我的模型實現爲structs
。其中幾個structs
的代表應該能夠根據用戶的操作修改模型。在Swift中傳遞值類型作爲參考
但是,當我將struct
傳遞給delegate
方法時,它會被複制。
你如何解決這個問題?你能強制編譯器通過這個struct
作爲參考,還是唯一的選擇是使用class
?
我在SWIFT 3.0中將我的模型實現爲structs
。其中幾個structs
的代表應該能夠根據用戶的操作修改模型。在Swift中傳遞值類型作爲參考
但是,當我將struct
傳遞給delegate
方法時,它會被複制。
你如何解決這個問題?你能強制編譯器通過這個struct
作爲參考,還是唯一的選擇是使用class
?
如果你想通過參考,你通常應該使用class
而不是struct
。
您可以同時使用類和結構定義自定義數據類型 用作你的程序代碼的基石。
但是,結構實例總是按值傳遞,而 實例總是按引用傳遞。這意味着他們是 適合不同類型的任務。當您考慮項目所需的數據結構和功能時,請決定 每個數據結構是定義爲類還是定義爲 結構。
首先使用struct的重點在於,這是可取的行爲。它保留了數據的不變性。 inout
可以實現這一點,但在一般情況下不推薦使用。
protocol Delegate {
func callback(_ oldValue: Int) -> Int
}
struct IncrementerDelegate: Delegate {
let step: Int
func callback(_ oldValue: Int) -> Int {
return oldValue + step
}
}
struct Model {
var i = 0
}
class Controller {
var model = Model()
var delegate: Delegate
init(delegate: Delegate) {
self.delegate = delegate
}
// To be called externally, such as by a button
func doSomething() {
// Delegate determains new value, but it's still the
// controller's job to perform the mutation.
model.i = delegate.callback(model.i)
}
}
let delegate = IncrementerDelegate(step: 5)
let controller = Controller(delegate: delegate)
print(controller.model.i)
controller.doSomething() // simulate button press
print(controller.model.i)
protocol CrappyDelegate {
func callback(_ model: inout Model)
}
struct CrappyIncrementerDelegate: CrappyDelegate {
let step: Int
func callback(_ model: inout Model) {
model.i = 9999999
// Just hijacked the models value,
// and the controller can't do anything about it.
}
}
class VulnerableController {
var model = Model()
var delegate: CrappyDelegate
init(delegate: CrappyDelegate) {
self.delegate = delegate
}
// To be called externally, such as by a button
func doSomething() {
// Controller leaks entire model, and has no control over what happens to it
delegate.callback(&model)
}
}
let crappyDelegate = CrappyIncrementerDelegate(step: 5)
let vulnerableController = VulnerableController(delegate: crappyDelegate)
print(controller.model.i)
controller.doSomething() // simulate button press
print(controller.model.i) // model hijacked
首先使用'struct'的重點在於,這是理想的行爲。它保留了數據的不變性。 'inout'可以做到這一點,但在一般情況下不推薦。爲什麼要複製一個問題? – Alexander
那麼如何從控制器修改模型?如果你的委託方法像Cocoa一樣通過模型傳遞模型,那麼委託人(通常是一個控制器)如何修改_real_模型,而不是副本? – cfischer
有點相關:[如何使用值類型對象作爲引用類型?](http://stackoverflow.com/q/41833469/2976878) – Hamish