Skip to content

Latest commit

 

History

History

FB13705327

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

TextField binded value stops changing after field is empty

Basic Information

Which platform is most relevant for your report?

iOS

Which technology does your report involve?

SwiftUI

What type of feedback are you reporting?

Incorrect/Unexpected Behavior

What build does the issue occur on?

iOS 17.4 Seed 3 (21E5200d)

Where does the issue occur?

On device

Description

  • Run the given code.
  • Try typing some numbers, and see the binded value update.
  • Delete the numbers until the field is empty. The value is correctly set to nil.
  • Try typing some numbers again, but this time the binded value won't update.
  • I would correctly expect the binded value to be set to nil when empty, but I would also expect the input to work just as normal after.

Evidence

Visual

Demo Workaround
Demo GIF Workaround GIF

Code

import SwiftUI
struct ContentView: View {
private static let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.usesGroupingSeparator = false
return formatter
}()
@State private var value: Double? = 3
var body: some View {
VStack {
TextField("Value", value: $value, formatter: Self.formatter)
.textFieldStyle(.roundedBorder)
.keyboardType(.decimalPad)
if let value {
Text("Value = \(value)")
} else {
Text("Value doesn't exist")
}
}
}
}
#Preview {
ContentView()
}

import SwiftUI
struct ContentView: View {
private static let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.usesGroupingSeparator = false
return formatter
}()
@FocusState private var focused: Bool
@State private var value: Double? = 3
@State private var valueString = Self.doubleToString(3)
var body: some View {
VStack {
TextField("Value", text: valueBinding())
.textFieldStyle(.roundedBorder)
.keyboardType(.decimalPad)
.focused($focused)
if let value {
Text("Value = \(value)")
} else {
Text("Value doesn't exist")
}
}
.onChange(of: focused) {
if !focused {
valueString = value.map(Self.doubleToString) ?? ""
}
}
}
private func valueBinding() -> Binding<String> {
Binding(
get: {
valueString
},
set: { new in
if new.isEmpty {
value = nil
valueString = ""
} else if let newValue = Double(new) {
value = newValue
valueString = Self.doubleToString(newValue)
// May be needed in the case that it is set more than once
if new.hasSuffix(Self.formatter.decimalSeparator) {
valueString.append(Self.formatter.decimalSeparator)
}
}
}
)
}
private static func doubleToString(_ value: Double) -> String {
let number = NSNumber(value: value)
return Self.formatter.string(from: number)!
}
}
#Preview {
ContentView()
}