繁体   English   中英

在结构上使用 Swift 协议委托来更改值?

[英]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仍将具有其原始值。 这是因为一旦你改变了你的FactoryOrderBook上的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM