Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SwiftUI:更新由其他@State变量组成的@Binding变量的最佳方法_Swift_Swiftui - Fatal编程技术网

SwiftUI:更新由其他@State变量组成的@Binding变量的最佳方法

SwiftUI:更新由其他@State变量组成的@Binding变量的最佳方法,swift,swiftui,Swift,Swiftui,我在SwiftUI中遇到了我的第一个复杂控件。它是一个日期频率选择器,用户可以选择每周定期事件的星期几,或每月定期事件的月份。我有@State变量来跟踪我的段控制器中的周与月,以及用户选择的周或月的哪一天。当这些值改变时,我想更新@Binding频率。下面的代码正在运行,但我觉得更新body call中的频率有点脏 enum Frequency { case weekly(on: Int) case monthly(on: Int) } struct FrequencyView

我在SwiftUI中遇到了我的第一个复杂控件。它是一个日期频率选择器,用户可以选择每周定期事件的星期几,或每月定期事件的月份。我有@State变量来跟踪我的段控制器中的周与月,以及用户选择的周或月的哪一天。当这些值改变时,我想更新@Binding频率。下面的代码正在运行,但我觉得更新body call中的频率有点脏

enum Frequency {
    case weekly(on: Int)
    case monthly(on: Int)
}

struct FrequencyView : View {
    @Binding var frequency: Frequency

    @State var segment: Int
    @State var weekDay: Int
    @State var monthDay: Int
    var displayFrequency: Frequency {
        if segment == 0 {
            return .weekly(on: weekDay)
        } else {
            return .monthly(on: monthDay)
        }
    }

    var body: some View {
        frequency = displayFrequency
        return NavigationView {
            VStack {
                Text(displayFrequency.long).fontWeight(.bold)
                SegmentedControl(selection: $segment) {
                    Text("Weekly").tag(0)
                    Text("Monthly").tag(1)
                }.padding()

                if segment == 0 {
                    Text("Day of the week").foregroundColor(Acorns.stone)
                    ExpensesWeeklyPickerView(day: $weekDay).padding()
                } else {
                    Text("Day of the month").foregroundColor(Acorns.stone)
                    ExpensesMonthlyPickerView(day: $monthDay).padding()
                }

                Spacer()
            }.navigationBarTitle(Text("Frequency"))
        }
    }
}

想知道是否有人找到了更好的方法吗?

首先,将
工作日
月日
的访问者添加到
频率

extension Frequency {
    var weekDay: Int {
        get {
            if case .weekly(on: let day) = self { return day }
            else { return 0 }
        }
        set { self = .weekly(on: newValue) }
    }

    var monthDay: Int {
        get {
            if case .monthly(on: let day) = self { return day }
            else { return 0 }
        }
        set { self = .monthly(on: newValue) }
    }
}
现在,您可以使用这些访问器为子视图创建绑定:

if segment == 0 {
    Text("Day of the week").foregroundColor(Acorns.stone)
    ExpensesWeeklyPickerView(day: $frequency.weekDay).padding()
} else {
    Text("Day of the month").foregroundColor(Acorns.stone)
    ExpensesMonthlyPickerView(day: $frequency.monthDay).padding()
}
要在单击某个段时更改频率,需要为
SegmentedControl
提供一个更改频率的绑定。我将介绍另一个(私有)
enum
用于该段:

fileprivate enum Segment: Int, Hashable {
    case weekly
    case monthly
}
然后在
频率
中添加一个扩展名,以转换为段:

extension Frequency {
    fileprivate var segment: ContentView.Segment {
        get {
            switch self {
            case .weekly(on: _): return .weekly
            case .monthly(on: _): return .monthly
            }
        }
        set {
            switch newValue {
            case .weekly: self = .weekly(on: 0)
            case .monthly: self = .monthly(on: 0)
            }
        }
    }
}
最后,去掉你的
segment
属性,改用
frequency.segment

        SegmentedControl(selection: $frequency.segment) {
            Text("Weekly").tag(Segment.weekly)
            Text("Monthly").tag(Segment.monthly)
        }.padding()
        if frequency.segment == .weekly {
           ...

谢谢你!这让我更进一步了。当分段状态变量改变时,我如何改变频率?要将@Binding频率从每周更改为每月,我已经添加到我的答案中。我必须警告您,这对我来说在Xcode 11 beta 3中崩溃了。我在用macOS Mojave跑步。如果你在卡塔琳娜的话,也许会有用。无论如何,我提交了一份关于坠机的错误报告。为了澄清这一点,当我将选择器设置从“第0天”改为“第0天”,然后单击另一段时,我的测试项目崩溃。