Wheel Pickers in form disappear after some show/hide cycles

[亡魂溺海] 提交于 2020-01-05 04:09:12

问题


I'm experiencing a strange behavior with wheel pickers embedded in a conditional subview. When the subview is shown, sometimes the values are not shown. Switching around between two conditional views, the values sometimes reappear. I've attached an animation showing the behavior and the full code. I can't find the reason for this.

Update: I've tried a lot of things to find the reason for this. Even after simplifying the revealing subform to just one single picker, replacing the foreach loop with hardcoded Text() entries, removing the framing and clipping on the picker, it still doesn't work.

import SwiftUI

fileprivate enum OpenSetting {
    case none, start, end
}

struct ContentView: View {
    @State private var openSetting = OpenSetting.none
    @State private var startMinutes = 0
    @State private var startSeconds = 10
    @State private var endMinutes = 3
    @State private var endSeconds = 0

    var body: some View {
        NavigationView {
            Form {
                // Start
                TimeSetting(
                    title: "Start",
                    color: Color.yellow,
                    minutes: startMinutes,
                    seconds: startSeconds,
                    setting: .start,
                    openSetting: $openSetting
                )
                if openSetting == .start {
                    TimePicker(minutes: $startMinutes, seconds: $startSeconds)
                }

                // End
                TimeSetting(
                    title: "End",
                    color: Color.green,
                    minutes: endMinutes,
                    seconds: endSeconds,
                    setting: .end,
                    openSetting: $openSetting
                )
                if openSetting == .end {
                    TimePicker(minutes: $endMinutes, seconds: $endSeconds)
                }
            }
                .navigationBarTitle("Test")
                .navigationBarItems(
                    trailing: Text("Start")
            )

        }

    }
}

struct TimeSetting: View {
    var title: String
    var color: Color
    var minutes: Int
    var seconds: Int
    fileprivate var setting: OpenSetting
    fileprivate var openSetting: Binding<OpenSetting>

    var body: some View {
        HStack {
            Text(title)
            Spacer()
            ZStack {
                RoundedRectangle(cornerRadius: 4)
                    .fill(color)
                Text(toTime(minutes: minutes, seconds: seconds))
            }
            .frame(width: 64, height: 32)
        }
        .contentShape(Rectangle())
        .onTapGesture {
            withAnimation() {
                self.openSetting.wrappedValue = (self.openSetting.wrappedValue == self.setting) ? OpenSetting.none : self.setting
            }
        }
    }

    func toTime(minutes: Int, seconds: Int) -> String {
        let timeString = String(format: "%02d", minutes) + ":" + String(format: "%02d", seconds)
        return timeString
    }
}

struct TimePicker: View {
    var minutes: Binding<Int>
    var seconds: Binding<Int>

    var body: some View {
        HStack() {
            Spacer()
            Picker(selection: minutes, label: EmptyView()) {
                ForEach((0...9), id: \.self) { ix in
                    Text("\(ix)").tag(ix)
                }
                }.pickerStyle(WheelPickerStyle()).frame(width: 50).clipped()
            Text("Min.")
            Picker(selection: seconds, label: EmptyView()) {
                ForEach((0...59), id: \.self) { ix in
                    Text("\(ix)").tag(ix)
                }
                }.pickerStyle(WheelPickerStyle()).frame(width: 50).clipped()
            Text("Sec.")
            Spacer()
        }
    }
}

回答1:


Using .id for Pickers seems helped. Tested with Xcode 11.2 / iOS 13.2.

var body: some View {
    HStack() {
        Spacer()
        Picker(selection: minutes, label: EmptyView()) {
            ForEach((0...9), id: \.self) { ix in
                Text("\(ix)").tag(ix)
            }
            }.pickerStyle(WheelPickerStyle()).frame(width: 50).clipped()
        .id(UUID().uuidString)
        Text("Min.")
        Picker(selection: seconds, label: EmptyView()) {
            ForEach((0...59), id: \.self) { ix in
                Text("\(ix)").tag(ix)
            }
            }.pickerStyle(WheelPickerStyle()).frame(width: 50).clipped()
        .id(UUID().uuidString)
        Text("Sec.")
        Spacer()
    }
}



回答2:


You can solve it with this way:

         if openSetting == .start {
                TimePicker1(minutes: $startMinutes, seconds: $startSeconds)
            }
          .......
            if openSetting == .end {
                TimePicker1(minutes: $endMinutes, seconds: $endSeconds).id(1)
            }

One with id, the other without id.



来源:https://stackoverflow.com/questions/59224408/wheel-pickers-in-form-disappear-after-some-show-hide-cycles

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!