簡體   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