Je suis nouveau sur Swift et SwiftUI et j'ai un modèle avec un @Published intValue facultatif et une vue avec un TextField où sa propriété text/string est liée dans les deux sens à intValue du modèle. Vous devez vous assurer que l'entrée de texte valide sous forme de chaîne est convertie en un entier valide pour le modèle. Quelle est l'approche recommandée pour gérer cela dans SwiftUI? Le code est similaire à celui ci-dessous ...
//Model
class AppModel:ObservedObject {
@Published
var intValue: Int? = 5
}
//View
@ObservedObject
var appModel = AppModel.shared
TextField("", text: $appModel.intValue)
.keyboardType(.numberPad)
Exemple de code mis à jour ...
///////////
import SwiftUI
class Model: ObservableObject {
static var shared: Model = Model()
@Published
var number: Int = 0
init(){}
}
struct ContentView: View {
var body: some View {
TextFieldFormatter()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct TextFieldFormatter: View {
@ObservedObject
var model: Model = Model.shared
@State private var number: Int = 0
let formatter: NumberFormatter = {
let numFormatter = NumberFormatter()
numFormatter.numberStyle = .none
return numFormatter
}()
var body: some View {
VStack {
Text("State").onTapGesture {
self.endEditing()
}
TextField("int", value: $number, formatter: formatter).keyboardType(.numberPad)
Text("Echo: \(number)")
Text("Observable")
TextField("int", value: $model.number, formatter: formatter).keyboardType(.numberPad)
Text("Echo: \(model.number)")
}
}
}
struct TextFieldFormatter_Previews: PreviewProvider {
static var previews: some View {
TextFieldFormatter()
}
}
extension View {
func endEditing() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to:nil, from:nil, for:nil)
}
}
TextField de SwiftUI a plusieurs constructeurs. L'un d'eux prend un paramètre Formatter.
https://developer.Apple.com/documentation/swiftui/textfield
import SwiftUI
struct TextFieldFormatter: View {
@ObservedObject var model: Model = Model.shared
let formatter: NumberFormatter = {
let numFormatter = NumberFormatter()
numFormatter.numberStyle = .none
return numFormatter
}()
var body: some View {
VStack {
Text("State").onTapGesture {
self.endEditing()
}
TextField("int", value: $model.number, formatter: formatter).keyboardType(.numberPad)
Text("Echo: \(model.number)")
Text("Observable")
TextField("int", value: $model.number, formatter: formatter).keyboardType(.numberPad)
Text("Echo: \(model.number)")
}
}
}
struct TextFieldFormatter_Previews: PreviewProvider {
static var previews: some View {
TextFieldFormatter()
}
}
De plus, si vous essayez de désactiver l'écran avec onTapGesture, vous pouvez envisager.
ajouter:
@State var disabled: Bool = false
et changer:
Form {
Text("Disable").onTapGesture {
//self.endEditing()
self.disabled = true
}
TextField("int", value: $model.number, formatter: formatter).keyboardType(.numberPad)
Text("Echo: \(model.number)")
Text("Observable")
TextField("int", value: $model.number, formatter: formatter).keyboardType(.numberPad)
Text("Echo: \(model.number)")
}.disabled($disabled.wrappedValue)
Donner des commentaires pendant que l'utilisateur tape peut être fait de différentes manières, mais une UITextView
personnalisée dans une classe UIViewRepresentable
semble être la plus courante.