为啥 TextField 不关注更新? (iOS 15)

Posted

技术标签:

【中文标题】为啥 TextField 不关注更新? (iOS 15)【英文标题】:Why is TextField not following the update? (iOS 15)为什么 TextField 不关注更新? (iOS 15) 【发布时间】:2021-10-20 10:20:33 【问题描述】:

由于某种原因,TextField 停止响应更改。

struct ContentView: View 
    @State private var number: Int = 0
    
    private var bindingNumber: Binding<Int> 
        .init 
            self.number
         set: 
            self.number = $0 % 10
        

    
    
    var body: some View 
        VStack 
            Text("number: \(self.number)")
            TextField("Number", value: self.bindingNumber, formatter: NumberFormatter())
                .disableAutocorrection(true)
                .background(Color.gray)
        
        .padding(.horizontal, 100)
    

如果您输入“44444”并完成编辑,TextField 不会将其值更改为“4”。 在 ios 14 中,此代码可以正常工作。

这是另一个例子:

struct ContentView: View 
    @State private var number: Int = 0
    @State private var numberRaw: Int = 0

    var body: some View 
        self.contentView
            .onChange(of: self.numberRaw)  newNumber in
                print("number: \(self.number) -> \(newNumber % 10)")
                self.number = newNumber % 10
            
            .onChange(of: self.number)  newNumber in
                print("numberRaw: \(self.numberRaw) -> \(newNumber)")
                self.numberRaw = newNumber
            
    
    
    private var contentView: some View 
        VStack 
            Text("Number: \(self.numberRaw)")
            TextField("Number", value: self.$numberRaw, formatter: NumberFormatter())
                .disableAutocorrection(true)
                .background(Color.gray)
        
        .padding(.horizontal, 100)
    

如果你输入“99”并关闭键盘,但“99”会留在屏幕上,日志会是:

number: 0 -> 9
numberRaw: 9 -> 9
number: 9 -> 9

我添加了一个 onSubmit 并且“Text”更新为“9”,但“TextField”仍然等于“99”。

.onSubmit 
  DispatchQueue.main.async 
    self.numberRaw = self.number
  

参数:MacBook Pro(13 英寸,M1,2020)、macOS 11.6、XCode 版本 13.0 (13A233)、iOS 15 模拟器。

当您启动应用程序时,问题就显现出来了,您立即输入一个大的。当你再次编辑它时,它就不再是问题了。

这就是它的工作原理,但不清楚为什么“TextField”本身不跟踪变化。

struct ContentView: View 
    @State private var number: Int = 0
    @State private var numberRaw: Int = 0
    @State private var showTextField: Bool = false

    var body: some View 
        VStack 
            Text("NumberRaw: \(self.numberRaw)")
            if self.showTextField 
                TextField("NumberRaw", value: self.$numberRaw, formatter: NumberFormatter())
                    .onSubmit 
                        self.showTextField = false
                    
                    .disableAutocorrection(true)
                    .background(Color.gray)
            
            else 
                Text("")
                    .onAppear 
                        self.numberRaw = self.number
                        self.showTextField = true
                    
            
        
        .padding(.horizontal, 100)
    

【问题讨论】:

它似乎对我有用,在 macos 12.01、xcode 13.1(RC)、目标 ios 15 和 macCatalyst 上。 Text 显示4,即44444 % 10 = 4 @workingdog 我的“文本”也更新了,“文本字段”没有更新。 TextField 显示 44444,但数字 == 4。 【参考方案1】:

你可以尝试这样的事情来实现你想要的:

struct ContentView: View 
    @State private var txt = ""
    @State private var number: Int = 0
    
    var body: some View 
        VStack (spacing: 55) 
            Text("number: \(number)")
            Text("txt: \(txt)")
            TextField("Number", text: $txt)
                .onChange(of: txt)  val in
                    if let rem = Int(val) 
                        number = rem % 10
                        txt = String(number)
                     else 
                        txt = ""
                        number = 0
                    
                
                .keyboardType(.numberPad)
                .disableAutocorrection(true)
                .background(Color.gray)
        
        .padding(.horizontal, 100)
    

【讨论】:

以上是关于为啥 TextField 不关注更新? (iOS 15)的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Textfield 控件不采用道具(类)?

在 TextField() 中为啥我们使用“onSubmitted:”语法?

为啥我的 QString 没有得到 TextField 的值?

为啥“cordova build ios”不更新 Xcode 项目?

调整窗口大小时,SwiftUI TextField 文本边界无法使用 GeometryReader 更新,导致外观错误

为啥我不能强制解开我的 $string 以用作 TextField 值?