ios - 具有关联值的开关内部的 Swift Mutation

标签 ios swift struct mutating-function

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

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 中使用这个变异函数 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 不是一个变异函数,所以那个 switch 里面的 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 函数?

最佳答案

根据 The Swift Programming Language :

A switch case can bind the value or values it matches to temporary constants or variables, for use in the body of the case. This behavior is known as value binding, because the values are bound to temporary constants or variables within the case’s body.

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

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

关于ios - 具有关联值的开关内部的 Swift Mutation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40345536/

相关文章:

ios - 我正在使用uiwebview中加载的内容可编辑html。隐藏/显示键盘时,我需要代码来设置光标位置

ios - 在 iOS 9.3/Xcode 7.3 中使用 StoreKit 常量时使用未解析的标识符

swift - swift 3.0 编译的模块无法在 Swift 3.0.1 中导入

ios - 无法使用 cocoapods 安装 RealmSwift

ios - 如何在 CNContact swift 中查看联系人来源?

ios - 无法获取用户当前位置

c - C 中的堆栈。存储 pop ant top 结果

c - 如何使用另一个文件中的结构?

c++98 结构体默认为零(除了一个值)

ios - 用户默认保存开关状态