Быстрая мутация внутри переключателя со связанными значениями

У меня есть эти структуры, которые я хочу мутировать:

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.

Другие вопросы по тегам