0

我有这些我想变异的结构:

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]
    }
}

我想在 SelectableArray 中使用这个变异 func select() 方法,我从一个变异函数链中调用它(因为 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 结构永远不会发生变异。我猜这个 switch 不是一个变异函数,所以var modes在那个 switch 里面是不可变的,然后下面的函数是否会发生任何变异都没有关系。我设法做的解决方法是:

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我可以使用的功能吗?

4

1 回答 1

2

根据Swift 编程语言

案例switch可以将它匹配的一个或多个值绑定到临时常量或变量,以在案例主体中使用。这种行为称为值绑定,因为值绑定到案例主体内的临时常量或变量。

对这种临时变量(例如modes变量)的更改不会影响正在打开的枚举的内容(例如kind)。

对于您的第一种工作方法,您确实需要一种不同类型的 switch 语句,该语句创建对枚举关联值的引用,从而允许您就地修改该值。Swift 3.0.1 中不存在这样的声明。

于 2016-10-31T16:05:54.413 回答