一些显示/隐藏循环后,形式中的选轮器消失

Posted

技术标签:

【中文标题】一些显示/隐藏循环后,形式中的选轮器消失【英文标题】:Wheel Pickers in form disappear after some show/hide cycles 【发布时间】:2019-12-07 08:50:20 【问题描述】:

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

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

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()
        
    

【问题讨论】:

确认 ios 13,.2 的行为,在 13.1 中没有发生 -> 我认为这是 Apple 错误 顺便说一句:你为​​什么不比较简单的方法? "if openSetting == .start " 并且使用 "withAnimation() self.openSetting.wrappedValue = (self.openSetting.wrappedValue == self.setting) ? OpenSetting.none : self.setting " @Chris:感谢您的确认。所以我需要找到一个解决方法。也感谢其他提示! 这个 SwiftUI 的 bug 真的让我很烦。我已经尽一切努力让它工作,但即使在一个简单的场景中,选轮器也不会出现。有人对此有解决方案吗? 【参考方案1】:

.id 用于Pickers 似乎有所帮助。使用 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】:

你可以这样解决:

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

一个带id,另一个不带id

【讨论】:

以上是关于一些显示/隐藏循环后,形式中的选轮器消失的主要内容,如果未能解决你的问题,请参考以下文章

在Javascript中隐藏一个按钮

LINQ 在使用 .Where() 循环和修改可枚举过滤器中的项目后,项目消失了 - 为啥? [复制]

如何设置一个DIV在网页中显示几秒然后自动隐藏消失?

在循环php jquery中隐藏和显示内容

隐藏/显示和启用/禁用按钮?

如何更改拾轮器线条的颜色和粗细? (斯威夫特用户界面)