点击条件部分中的文本字段时应用程序冻结

发布于 2025-01-09 22:48:30 字数 1524 浏览 2 评论 0原文

我有一个可以通过编程方式修改的文本字段。 它工作正常,直到有条件地显示表单部分,在这种情况下,当我使用文本字段时应用程序会冻结。

这是我的代码(我删除了不必要的东西):

struct test: View {
    @Environment(\.presentationMode) var presentationMode
    @State private var displaySection = true
    @State private var amount: Double?
    @FocusState private var isFocused: Bool
    
    var body: some View {
        NavigationView{
            Form {
                if displaySection {     // <-- works well without that condition, otherwise app freezes
                    Section {
                        VStack {
                            HStack {
                                Text("Amount EUR")
                                Spacer()
                                TextField("Type amount", value: $amount, format: .number)
                                    .keyboardType(.numberPad)
                                    .multilineTextAlignment(.trailing)
                                    .focused($isFocused)
                            }
                            Text("Set MAX (999)")
                                .frame(maxWidth: .infinity, alignment: .leading)
                                .onTapGesture {
                                    isFocused = false
                                    amount = 999
                                }
                        }
                    }
                }
            }
        }
    }
}

我需要在表单中隐藏一些部分,所以我坚持这一点,没有成功地解决这个问题。问题出现在模拟器上以及设备上。

这种行为是否正常,或者是否有可能的解决方法? 感谢您的帮助 :)

I have a textfield that can be modified programatically.
It works fine, until the form section is conditionally displayed, in that case the app freezes when I use the textfield.

Here is my code (I removed unnecessary stuff):

struct test: View {
    @Environment(\.presentationMode) var presentationMode
    @State private var displaySection = true
    @State private var amount: Double?
    @FocusState private var isFocused: Bool
    
    var body: some View {
        NavigationView{
            Form {
                if displaySection {     // <-- works well without that condition, otherwise app freezes
                    Section {
                        VStack {
                            HStack {
                                Text("Amount EUR")
                                Spacer()
                                TextField("Type amount", value: $amount, format: .number)
                                    .keyboardType(.numberPad)
                                    .multilineTextAlignment(.trailing)
                                    .focused($isFocused)
                            }
                            Text("Set MAX (999)")
                                .frame(maxWidth: .infinity, alignment: .leading)
                                .onTapGesture {
                                    isFocused = false
                                    amount = 999
                                }
                        }
                    }
                }
            }
        }
    }
}

I need to have some sections hidden in the form so I'm stuck on that, didn't succeed to skirt this issue. Problem appears on simulator as well on device.

Is this behavior normal, or is there a possible workaround ?
Thanks for your help :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

染柒℉ 2025-01-16 22:48:30

因此,使用 Intel 和 iOS 15.2 上的 Xcode 13.2.1,如果我在“欧元金额”中输入超过三位数的数字,然后尝试在模拟器和真实设备上锁定此示例代码,则我只能获得该示例代码。 “将最大值设置为 999”,即三位数。

在以前版本的 SwiftUI 中,TextField 唯一可以使用的输入绑定是 String。看起来虽然当前版本接受绑定到数字,但它执行此操作的方式是映射,并且底层机制仍然是基于原始字符串的 TextField 的机制(使用附加键盘在 TextField 中键入仍然不幸地呈现非数字字符无论键盘类型如何,就像我上次尝试的那样 https://gist.github.com/shufflingB/23daafa5253c3355cdf18934599cd54c

无论出于何种原因,当输入超过三位数字并且 TextField 时,这个新的(ish)映射过程似乎会变得混乱然后默认自动添加数字分组字符。

两种解决方法似乎可以解决该问题:

  1. 使用 Set the Max ... 触发的对 amount 的更改推送到稍后的状态更新周期DispatchQueue.main.asyncAfter

  2. Give从文本字段中删除麻烦的分组字符的选项。

struct ContentView: View {
    @Environment(\.presentationMode) var presentationMode
    @State private var displaySection = true
    @State private var amount: Double?
    @FocusState private var isFocused: Bool

    var body: some View {
        NavigationView {
            Form {
                if displaySection {
                    Section {
                        VStack {
                            HStack {
                                Text("Amount EUR")
                                Spacer()
                                TextField("Type amount", value: $amount, format: .number)
                                    .keyboardType(.numberPad)
                                    .multilineTextAlignment(.trailing)
                                    .focused($isFocused)

                                /* Alternative to Dispatch, remove number grouping
                                TextField("Type amount", value: $amount, format: .number.grouping(.never))
                                    .keyboardType(.numberPad)
                                    .multilineTextAlignment(.trailing)
                                    .focused($isFocused)
                                 */
                            }
                            Text("Set MAX (999)")
                                .frame(maxWidth: .infinity, alignment: .leading)
                                .onTapGesture {
                                    isFocused = false
                                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { // <- Push change to subsequent update cycle
                                        amount = 999
                                    }
                                }
                        }
                    }
                }
            }
        }
    }
}

So with Xcode 13.2.1 on Intel and iOS 15.2 I can only get this example code to lock-up in the simulator and on a real device if I type a number of more than three digits in the 'Amount EUR' and then attempt to 'Set the Max to 999' i.e. a three digit number.

In previous versions of SwiftUI the only input binding TextField would work with was String. It seems likely that although the current version accepts binding to numerics the way it is doing this is to map, and the underlying mechanism remains that of the original String based TextField (typing in the TextField with an attached keyboard still unfortunately renders non-numeric characters regardless of keyboardType as it did the last time I experimented https://gist.github.com/shufflingB/23daafa5253c3355cdf18934599cd54c)

For whatever reason this new(ish) mapping process appears to be getting confused when more than three digits are entered and the TextField is then by default automatically adding a number grouping character.

Two work-arounds seem to address the problem:

  1. Push the change to amount triggered by Set the Max ... to a later state update cycle using DispatchQueue.main.asyncAfter

  2. Give an option to remove the troublesome grouping character from the TextField.

struct ContentView: View {
    @Environment(\.presentationMode) var presentationMode
    @State private var displaySection = true
    @State private var amount: Double?
    @FocusState private var isFocused: Bool

    var body: some View {
        NavigationView {
            Form {
                if displaySection {
                    Section {
                        VStack {
                            HStack {
                                Text("Amount EUR")
                                Spacer()
                                TextField("Type amount", value: $amount, format: .number)
                                    .keyboardType(.numberPad)
                                    .multilineTextAlignment(.trailing)
                                    .focused($isFocused)

                                /* Alternative to Dispatch, remove number grouping
                                TextField("Type amount", value: $amount, format: .number.grouping(.never))
                                    .keyboardType(.numberPad)
                                    .multilineTextAlignment(.trailing)
                                    .focused($isFocused)
                                 */
                            }
                            Text("Set MAX (999)")
                                .frame(maxWidth: .infinity, alignment: .leading)
                                .onTapGesture {
                                    isFocused = false
                                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { // <- Push change to subsequent update cycle
                                        amount = 999
                                    }
                                }
                        }
                    }
                }
            }
        }
    }
}

快乐很简单 2025-01-16 22:48:30

分而治之。

你在你的应用程序中呈现了一个非常奇怪的行为,我永远不会想象这样的错误。我测试了你的代码,它实际上冻结了应用程序。

现在,我测试了以下解决方案:将您的 Section 移动到单独的视图。在我的 Xcode 中,它可以工作。

struct Example: View {
    @Environment(\.presentationMode) var presentationMode
    @State private var displaySection = true
    
    var body: some View {
        NavigationView{
            Form {
                if displaySection {     // <-- works well ALSO WITH that condition
                    ConditionalSection()
                }
                
                Button {
                    withAnimation {
                        displaySection.toggle()
                    }
                } label: {
                    Text("Display or not display?")
                }
            }
        }
    }
}

struct ConditionalSection: View {
    @State private var amount: Double?
    @FocusState private var isFocused: Bool
    
    var body: some View {
        Section {
            VStack {
                HStack {
                    Text("Amount EUR")
                    Spacer()
                    TextField("Type amount", value: $amount, format: .number)
                        .keyboardType(.numberPad)
                        .multilineTextAlignment(.trailing)
                        .focused($isFocused)
                }
                Text("Set MAX (999)")
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .onTapGesture {
                        isFocused = false
                        amount = 999
                    }
            }
        }

    }
}

Divide and conquer.

You presented a really weird behaviour in your app, I would never imagine such bug. I tested your code, it actually freezes the app.

Now, I tested the solution below: move your Section to a separate view. In my Xcode, it works.

struct Example: View {
    @Environment(\.presentationMode) var presentationMode
    @State private var displaySection = true
    
    var body: some View {
        NavigationView{
            Form {
                if displaySection {     // <-- works well ALSO WITH that condition
                    ConditionalSection()
                }
                
                Button {
                    withAnimation {
                        displaySection.toggle()
                    }
                } label: {
                    Text("Display or not display?")
                }
            }
        }
    }
}

struct ConditionalSection: View {
    @State private var amount: Double?
    @FocusState private var isFocused: Bool
    
    var body: some View {
        Section {
            VStack {
                HStack {
                    Text("Amount EUR")
                    Spacer()
                    TextField("Type amount", value: $amount, format: .number)
                        .keyboardType(.numberPad)
                        .multilineTextAlignment(.trailing)
                        .focused($isFocused)
                }
                Text("Set MAX (999)")
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .onTapGesture {
                        isFocused = false
                        amount = 999
                    }
            }
        }

    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文