[英]Using Swift protocol delegation on a struct to change values?
我有一个项目,我希望有可以变异的orders
(一个Ints
数组)的factories
。
我希望另一个 class 中的所有代码变异、添加、删除、验证等订单(即:几乎像代理模式),并在准备好时用新订单更新工厂。
我按照委托模式将新订单踢回工厂进行更新,但是工厂订单永远不会更新。
注意:我知道这是因为工厂是一个struct
并且它是一个值类型
我想知道是否可以使用委托模式更新结构; 或者我必须将其更改为引用类型(类)才能解决问题。
在下面的代码中,我删除了所有验证、推送、弹出和其他功能,并通过强制更改订单数组然后使用委托来回退更改的订单来保持此查询的简单性。
// 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)")
Output:
Book.orders = [7, 8, 1]
Shop.orders = [1, 2, 3]
同样,我知道原因是因为我已将 factory 声明为struct
; 但我想知道是否可以使用委托模式来改变结构中的订单数组?
如果没有,我将其更改为 class; 但我很感激对此的任何反馈。
感谢
您的代码存在 2 个问题,这两个问题都需要修复才能正常工作:
设置委托后,您将看到ordersDidUpdate
实际被调用,但shop.orders
仍将具有其原始值。 这是因为一旦你改变了你的Factory
, OrderBook
上的delegate
集将与变异的Factory
不同的 object ,后者在委托调用ordersDidUpdate
中更新。
使用引用类型可解决此问题。
切换到class
代表时要记住几件事。 使您的OrderUpdatedDelegate
成为类绑定协议,然后从 function 声明中删除mutating
。 最重要的是,始终将类绑定委托声明为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)")
正如您所说,由于Factory
是一个结构,因此在设置OrderBook
delegate
时,它已经复制到那里,因此该delegate
实际上是您原始工厂实例的副本。
class
是适合此问题的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.