Swiftui 在一些显示/隐藏循环后,形式上的车轮选择器消失

Swiftui 在一些显示/隐藏循环后,形式上的车轮选择器消失,swiftui,picker,Swiftui,Picker,我在条件子视图中嵌入了车轮选择器,遇到了一种奇怪的行为。显示子视图时,有时不显示值。在两个条件视图之间切换时,值有时会重新出现。我附加了一个动画,显示了行为和完整的代码。我找不到原因 更新:我已经尝试了很多方法来寻找原因。即使将显示子窗体简化为一个选择器,用硬编码的Text()项替换foreach循环,删除选择器上的框架和剪辑,它仍然不起作用 导入快捷界面 fileprivate枚举打开设置{ 案例无、开始、结束 } 结构ContentView:View{ @State private var

我在条件子视图中嵌入了车轮选择器,遇到了一种奇怪的行为。显示子视图时,有时不显示值。在两个条件视图之间切换时,值有时会重新出现。我附加了一个动画,显示了行为和完整的代码。我找不到原因

更新:我已经尝试了很多方法来寻找原因。即使将显示子窗体简化为一个选择器,用硬编码的Text()项替换foreach循环,删除选择器上的框架和剪辑,它仍然不起作用

导入快捷界面
fileprivate枚举打开设置{
案例无、开始、结束
}
结构ContentView:View{
@State private var openSetting=openSetting.none
@国家私有var startMinutes=0
@国家私有变量startSeconds=10
@国家私有变量endMinutes=3
@状态专用变量endSeconds=0
var body:一些观点{
导航视图{
形式{
//开始
时间设置(
标题:“开始”,
颜色:颜色,黄色,
分钟:开始,
秒:开始秒,
设置:。开始,
openSetting:$openSetting
)
如果openSetting==.start{
计时器选择器(分钟:$startMinutes,秒:$startSeconds)
}
//结束
时间设置(
标题:“结束”,
颜色:颜色,绿色,
分钟:结束分钟,
秒:结束秒,
设置:。结束,
openSetting:$openSetting
)
如果openSetting==.end{
计时器选择器(分钟:$endMinutes,秒:$endSeconds)
}
}
.navigationBarTitle(“测试”)
.航海术语(
尾随:文本(“开始”)
)
}
}
}
结构时间设置:视图{
变量标题:字符串
颜色:颜色
分钟数:Int
变量秒:Int
fileprivate变量设置:OpenSetting
fileprivate var openSetting:绑定
var body:一些观点{
HStack{
正文(标题)
垫片()
ZStack{
圆角转角(拐角半径:4)
.填充(颜色)
文本(toTime(分:分,秒:秒))
}
.框架(宽:64,高:32)
}
.contentShape(矩形())
.ontapsigne{
withAnimation(){
self.openSetting.wrappedValue=(self.openSetting.wrappedValue==self.setting)?openSetting.none:self.setting
}
}
}
func toTime(分钟:Int,秒:Int)->字符串{
让时间字符串=字符串(格式:“%02d”,分钟)++”:“+字符串(格式:“%02d”,秒)
返回时间串
}
}
结构时间选择器:视图{
var分钟数:绑定
var秒:绑定
var body:一些观点{
HStack(){
垫片()
选择器(选择:分钟,标签:EmptyView()){
ForEach((0…9),id:\.self){ix in
文本(“\(ix)”).tag(ix)
}
}.pickerStyle(WheelPickerStyle()).frame(宽度:50).clipped()
文本(“最小值”)
选择器(选择:秒,标签:EmptyView()){
ForEach((0…59),id:\.self){ix in
文本(“\(ix)”).tag(ix)
}
}.pickerStyle(WheelPickerStyle()).frame(宽度:50).clipped()
文本(“第节”)
垫片()
}
}
}

选择器使用
.id
似乎有帮助。使用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()
    }
}

您可以通过以下方式解决此问题:

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

一个有
id
,另一个没有
id

确认iOS 13.2的行为,在13.1中没有发生->我想这是一个苹果的错误顺便问一下:你为什么不比较一下简单的方法呢?“如果openSetting=.start{”并且动画更平滑,则使用“withAnimation(){self.openSetting.wrappedValue=(self.openSetting.wrappedValue==self.setting)?openSetting.none:self.setting}”@克里斯:谢谢你的确认。所以我需要找到一个解决方法。也谢谢你的其他提示!这个SwiftUI错误真的让我很恼火。我已经尝试了一切让它工作,但即使在一个简单的场景中,捡拾器也没有出现。有人有解决方法吗?更新:不幸的是,这个解决方案确实解决了初始化问题问题,但它引入了一个新的严重问题:当使用其中一个控制盘更改值时,应用程序崩溃,系统库中出现“下标超出范围”错误。
         if openSetting == .start {
                TimePicker1(minutes: $startMinutes, seconds: $startSeconds)
            }
          .......
            if openSetting == .end {
                TimePicker1(minutes: $endMinutes, seconds: $endSeconds).id(1)
            }