web-dev-qa-db-fra.com

Swift et liaison SwiftUI de la chaîne TextField à la propriété Integer facultative publiée du modèle

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)
    }
}
3
Erik Peterson

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.

1
CranialDev