Быстрая мутация внутри переключателя со связанными значениями
У меня есть эти структуры, которые я хочу мутировать:
public struct CheckoutViewModel {
var sections: [Section]
var total: String
public struct Section {
var title: String
var description: String
var kind: Kind
var expandState: ExpandState
enum Kind {
case products([ProductOrderViewModel])
case shippingMode(SelectableArray<ShippingMode>)
case shippingTarget(SelectableArray<ShippingKind>)
case billingAddress(SelectableArray<Address>)
case payment(SelectableArray<PaymentProvider>)
case promoCode(String?)
case legalAdvice(userAccepted: Bool)
}
}
}
struct SelectableArray<T> {
var selectedIndex: Int?
let options: [T]
init(options: [T]) {
self.options = options
self.selectedIndex = nil
}
mutating func select(atIndex: Int) throws -> T {
guard atIndex < options.count else {
throw SelectableArrayError.outOfBoundsIndex
}
selectedIndex = atIndex
return options[atIndex]
}
var selectedElement: T? {
guard let selectedIndex = selectedIndex else { return nil }
return options[selectedIndex]
}
}
Я хочу использовать этот мутирующий метод func select() внутри SelectableArray, я вызываю его из цепочки мутирующих функций (потому что Sections вложен в структуру)
extension CheckoutViewModel {
mutating func select(atIndexPath indexPath: IndexPath) {
sections[indexPath.section].select(atIndex: indexPath.row)
}
}
extension CheckoutViewModel.Section {
mutating func select(atIndex idx: Int) {
switch kind {
case .shippingMode(var modes):
do { _ = try modes.select(atIndex: idx) } catch { return }
default:
return nil
}
dump(self) // Here self hasn't changed
}
}
Проблема в том, что структура CheckoutViewModel никогда не видоизменяется. Я предполагаю, что переключатель не является мутирующей функцией, поэтому var modes
внутри этого переключателя он не является изменяемым, и тогда не имеет значения, изменяют ли что-либо следующие функции. Обходной путь мне удалось сделать это:
mutating func select(atIndex idx: Int) {
switch kind {
case .shippingMode(var modes):
do {
_ = try modes.select(atIndex: idx)
self.kind = .shippingMode(modes)
} catch { return }
default:
return
}
}
У вас есть другое решение этой проблемы? Есть ли какой-нибудь mutating switch
функция, которую я могу использовать?
1 ответ
Согласно языку программирования Swift:
switch
case может привязывать значение или значения, которые ему соответствуют, к временным константам или переменным для использования в теле case. Такое поведение известно как привязка значений, поскольку значения привязаны к временным константам или переменным в теле кейса.
Изменения в такой временной переменной (например, modes
переменная) не влияет на содержимое включаемого перечисления (например, kind
).
Для первого подхода к работе вам действительно понадобится оператор оператора switch другого типа, который создает ссылку на ассоциированное значение enum, позволяя вам изменить это значение на месте. Такого утверждения нет в Swift 3.0.1.