在结构上使用 Swift 协议委托来更改值?
Using Swift protocol delegation on a struct to change values?
我有一个项目,我希望有 factories
和 orders
(Ints
的数组)可以改变。
我希望所有代码在另一个 class 中修改、添加、删除、验证等订单(即:几乎像代理模式),并在准备好时用新订单更新工厂。
我按照委托模式将新订单踢回工厂进行更新,但是工厂订单永远不会更新。
注意:我知道这是因为工厂是一个struct
并且它是一个值类型
我想知道是否可以使用委托模式更新结构;或者我必须将其更改为引用类型 (a class) 才能解决问题。
在下面的代码中,我删除了所有验证、推送、弹出和其他功能,并通过强制更改订单数组然后使用委托回退更改的订单来保持此查询的简单性。
// Swift playground code
protocol OrderUpdatedDelegate {
mutating func ordersDidUpdate(_ orders: [Int])
}
// This class will handle all the validation to do with
// orders array, but for now; lets just force
// change the orders to test the delegate pattern
class OrderBook {
var delegate: OrderUpdatedDelegate?
var orders: [Int] = [Int]()
init(orders: [Int]) {
self.orders = orders
}
func changeOrders() {
self.orders = [7,8,1]
print ("updated orders to -> \(orders)")
delegate?.ordersDidUpdate(orders)
}
}
struct Factory {
var orders: [Int] = [Int]()
init(orders: [Int]) {
self.orders = orders
}
}
extension Factory: OrderUpdatedDelegate {
mutating func ordersDidUpdate(_ orders: [Int]) {
print ("recieved: \(orders)")
self.orders = orders
}
}
var shop = Factory(orders: [1,2,3])
let book = OrderBook.init(orders: shop.orders)
book.changeOrders()
print ("\nBook.orders = \(book.orders)")
print ("Shop.orders = \(shop.orders)")
输出:
Book.orders = [7, 8, 1]
Shop.orders = [1, 2, 3]
同样,我知道原因是因为我已将工厂声明为 struct
;但我想知道是否可以使用委托模式来改变结构中的订单数组?
如果没有,我会把它改成class;但我很感激对此的任何反馈。
谢谢
正如你所说,因为 Factory
是一个结构,当设置 OrderBook
delegate
它已经复制到那里所以 delegate
实际上是你原始工厂实例的副本.
class
是适合此问题的解决方案。
您的代码有 2 个问题,这两个问题都需要修复才能正常工作:
- 使用值类型
- 没有设置委托
设置委托后,您会看到 ordersDidUpdate
实际被调用,但 shop.orders
仍将具有其原始值。这是因为一旦您改变 Factory
,OrderBook
上设置的 delegate
将与在委托调用中更新的 Factory
不同的对象 ordersDidUpdate
.
使用引用类型修复了这个问题。
当您切换到 class
代表时,请记住几件事。使您的 OrderUpdatedDelegate
成为 class 绑定协议,然后从函数声明中删除 mutating
。最重要的是,始终将 class 绑定的委托声明为 weak
以避免强引用循环。
protocol OrderUpdatedDelegate: class {
func ordersDidUpdate(_ orders: [Int])
}
// This class will handle all the validation to do with
// orders array, but for now; lets just force
// change the orders to test the delegate pattern
class OrderBook {
weak var delegate: OrderUpdatedDelegate?
var orders: [Int] = []
init(orders: [Int]) {
self.orders = orders
}
func changeOrders() {
self.orders = [7,8,1]
print ("updated orders to -> \(orders)")
delegate?.ordersDidUpdate(orders)
}
}
class Factory {
var orders: [Int] = []
init(orders: [Int]) {
self.orders = orders
}
}
extension Factory: OrderUpdatedDelegate {
func ordersDidUpdate(_ orders: [Int]) {
print("receieved: \(orders)")
self.orders = orders
print("updated order: \(self.orders)")
}
}
var shop = Factory(orders: [1,2,3])
let book = OrderBook(orders: shop.orders)
book.delegate = shop
book.changeOrders()
print ("Book.orders = \(book.orders)")
print ("Shop.orders = \(shop.orders)")
我有一个项目,我希望有 factories
和 orders
(Ints
的数组)可以改变。
我希望所有代码在另一个 class 中修改、添加、删除、验证等订单(即:几乎像代理模式),并在准备好时用新订单更新工厂。
我按照委托模式将新订单踢回工厂进行更新,但是工厂订单永远不会更新。
注意:我知道这是因为工厂是一个struct
并且它是一个值类型
我想知道是否可以使用委托模式更新结构;或者我必须将其更改为引用类型 (a class) 才能解决问题。
在下面的代码中,我删除了所有验证、推送、弹出和其他功能,并通过强制更改订单数组然后使用委托回退更改的订单来保持此查询的简单性。
// Swift playground code
protocol OrderUpdatedDelegate {
mutating func ordersDidUpdate(_ orders: [Int])
}
// This class will handle all the validation to do with
// orders array, but for now; lets just force
// change the orders to test the delegate pattern
class OrderBook {
var delegate: OrderUpdatedDelegate?
var orders: [Int] = [Int]()
init(orders: [Int]) {
self.orders = orders
}
func changeOrders() {
self.orders = [7,8,1]
print ("updated orders to -> \(orders)")
delegate?.ordersDidUpdate(orders)
}
}
struct Factory {
var orders: [Int] = [Int]()
init(orders: [Int]) {
self.orders = orders
}
}
extension Factory: OrderUpdatedDelegate {
mutating func ordersDidUpdate(_ orders: [Int]) {
print ("recieved: \(orders)")
self.orders = orders
}
}
var shop = Factory(orders: [1,2,3])
let book = OrderBook.init(orders: shop.orders)
book.changeOrders()
print ("\nBook.orders = \(book.orders)")
print ("Shop.orders = \(shop.orders)")
输出:
Book.orders = [7, 8, 1]
Shop.orders = [1, 2, 3]
同样,我知道原因是因为我已将工厂声明为 struct
;但我想知道是否可以使用委托模式来改变结构中的订单数组?
如果没有,我会把它改成class;但我很感激对此的任何反馈。
谢谢
正如你所说,因为 Factory
是一个结构,当设置 OrderBook
delegate
它已经复制到那里所以 delegate
实际上是你原始工厂实例的副本.
class
是适合此问题的解决方案。
您的代码有 2 个问题,这两个问题都需要修复才能正常工作:
- 使用值类型
- 没有设置委托
设置委托后,您会看到 ordersDidUpdate
实际被调用,但 shop.orders
仍将具有其原始值。这是因为一旦您改变 Factory
,OrderBook
上设置的 delegate
将与在委托调用中更新的 Factory
不同的对象 ordersDidUpdate
.
使用引用类型修复了这个问题。
当您切换到 class
代表时,请记住几件事。使您的 OrderUpdatedDelegate
成为 class 绑定协议,然后从函数声明中删除 mutating
。最重要的是,始终将 class 绑定的委托声明为 weak
以避免强引用循环。
protocol OrderUpdatedDelegate: class {
func ordersDidUpdate(_ orders: [Int])
}
// This class will handle all the validation to do with
// orders array, but for now; lets just force
// change the orders to test the delegate pattern
class OrderBook {
weak var delegate: OrderUpdatedDelegate?
var orders: [Int] = []
init(orders: [Int]) {
self.orders = orders
}
func changeOrders() {
self.orders = [7,8,1]
print ("updated orders to -> \(orders)")
delegate?.ordersDidUpdate(orders)
}
}
class Factory {
var orders: [Int] = []
init(orders: [Int]) {
self.orders = orders
}
}
extension Factory: OrderUpdatedDelegate {
func ordersDidUpdate(_ orders: [Int]) {
print("receieved: \(orders)")
self.orders = orders
print("updated order: \(self.orders)")
}
}
var shop = Factory(orders: [1,2,3])
let book = OrderBook(orders: shop.orders)
book.delegate = shop
book.changeOrders()
print ("Book.orders = \(book.orders)")
print ("Shop.orders = \(shop.orders)")