SwiftUI UITextfield

SireneMoewe

Erdapfel
Mitglied seit
02.04.20
Beiträge
5
Guten Tag,

Zur Zeit möchte ich SwiftUI lernen, mit wenig bis keinen Vorkenntnissen in Bezug auf Programmieren. Das ist natürlich nicht so einfach. Jetzt möchte ich ein UITextfield erstellen und nutze Xcode 11.3.1. Ich hab auch schon ewig viel gesucht, aber die Anleitungen dafür beziehen sich fast alle nur auf StoryBoard und ViewController. Den ViewController gibts in Swift 5 nicht mehr und das ist eben das Problem.

Ich brauche das UITextfield, da ich mit "textfieldShouldReturn" den Return-Befehl des Keyboards abgreifen muss. Deshalb bräuchte ich die Hilfe eines SwiftUI-Experten!!

Viele Grüße
SireneMoewe
 

Scotch

Lohrer Rambour
Mitglied seit
02.12.08
Beiträge
6.859
Wenn in deinem Beitrag eine Frage enthalten ist, hast du sie so gut versteckt, dass zumindest ich sie nicht gefunden habe ;)
 
  • Like
Wertungen: Prince of Whales

Marcel Bresink

Maunzenapfel
Mitglied seit
28.05.04
Beiträge
5.386
Ich vermute außerdem, dass hier irgendwie Swift und SwiftUI miteinander verwechselt werden.
 

Scotch

Lohrer Rambour
Mitglied seit
02.12.08
Beiträge
6.859
Ich vermute, dass das die Antwort wäre, wenn es eine Frage gäbe ;)
 

SireneMoewe

Erdapfel
Mitglied seit
02.04.20
Beiträge
5
Ich vermute außerdem, dass hier irgendwie Swift und SwiftUI miteinander verwechselt werden.
Das ist mir gestern auch aufgefallen ;)
Das Problem ist dieses: In SwiftUI kann ich die Eingaben in einem Textfeld erst mit "Enter" auf dem Keyboard des iPhones "bestätigen". Ich möchte aber in der App einen Button einbauen, der mir dieses "Bestätigen" des Wertes im Textfeld abnimmt. Also möchte ich die Enter-Funktion des iPhone Keyboards abgreifen und auf einen beliebigen Button in der App übertragen. Wie funktioniert das in SwiftUI?
 

Dx667

Pomme au Mors
Mitglied seit
26.11.17
Beiträge
862
Das Storyboard und den zugehörigen ViewController gibt es in Swift 5 natürlich noch genauso. Die „gehören“ aber zu UIKit.

SwiftUI ist ein beschreibender Ansatz, insofern ist das klassische Storyboard sinnlos.

Wenn ich dein Problem richtig verstanden habe ist die Lösung ein onCommit closure.
wie zB hier beschrieben:

Ich habe mich aber nie wirklich mit SwiftUI beschäftigt, dazu ist das Ding noch viel zu instabil.
 

SireneMoewe

Erdapfel
Mitglied seit
02.04.20
Beiträge
5
Danke für die Antwort. Die Befehle "onCommit" und "onEditingChange" kenn ich, kann sie aber nicht richtig anwenden..

Hier hab ich mal den Code dabei, damit man sich das besser vorstellen kann.
Swift:
import SwiftUI

struct Beispiel: View {
    
    @State var Gewicht: Float = 0.00
    
    private var Decimal: NumberFormatter = {
        let f = NumberFormatter()
        f.numberStyle = .decimal
        f.usesSignificantDigits = true
        f.minimumSignificantDigits = 0
        f.maximumSignificantDigits = 4
        return f
    }()
    
    var body: some View {
  
        HStack {
        
            TextField("", value: $Gewicht, formatter: Decimal, onCommit: {})
        }
   }

struct Beispiel_Previews: PreviewProvider {
    static var previews: some View {
        Beispiel()
    }
}
Blöd ist natürlich auch, dass die Variable als Float ausgegeben wird, aber das muss leider sein.
Komme ich da mit "onCommit" oder "onEditingChange" irgendwie weiter?
 

Dx667

Pomme au Mors
Mitglied seit
26.11.17
Beiträge
862
Hm? Vorweg nochmal...mit SwiftUI habe ich mir nur sehr kurz beschäftigt. Aber ich versuche es mal...

Was soll passieren wenn du in dem Feld die Enter Taste drückst?
In dem Beispiel fehlt ja was du dann mit der Variable machen willst.

Testweise kannst du in deine closure etwas eingeben wie zB.
onCommit: { print("enter key tapped") })

Dann siehst du ob und wann die closure aufgerufen wird. Aber im Endeffekt muss du in onCommit angeben was weiter passieren soll...

Ein Tipp unabhängig von deiner Frage: Bitte schmeiß die Deutschen Begriffe aus dem Code...und in Swift sollten Variable in lowerCamelCase geschrieben sein...in deinem Fall zB 'weight' oder wenn es länger wird 'myDogsWeight'.
Das macht dir das Leben auf Dauer in jedem Fall einfacher...
 

SireneMoewe

Erdapfel
Mitglied seit
02.04.20
Beiträge
5
Ein Problem hab ich jetzt gefunden: Die Funktion "onCommit" und "onEditingChange" funktionieren nur, wenn man als Variable im Textfeld einen String verwendet. Da ich aber im Textfeld einen Float nutze, gibts hier Schwierigkeiten. Also müsste ich den String in Float konvertieren. Wenn ich es so versuche
Code:
@State var weight: String = ""
    
    var weight1 = Float(weight)
bekomm ich aber diesen Fehler: "Cannot use instance member 'weight' within property initializer; property initializers run before 'self' is available". Auch bei anderen Möglichkeiten bekomme ich immer diesen doofen Fehler. Hat jemand eine Idee, was man dagegen machen kann?

Danke übrigens schon mal für die Hilfe. Ich werde mich bemühen, alle deutschen Begriffe zu entfernen ;)
 

Dx667

Pomme au Mors
Mitglied seit
26.11.17
Beiträge
862
Hängt jetzt vom genauen Kontext ab...ich denke aber ein ‚lazy var weight1 = Float(weight)‘ löst das Problem.

Ich würde es aber erst umwanden wenn du die variable brauchst zB:
let surface = (Float(weight) * Float(height))

Achtung...du musst die Variable auch gegen eine Fehleingabe absichern.
Wenn dein Nutzer statt ‚68.4‘ zB ‚Hansi‘ eingibt fliegt dir das Ding um die Ohren.
 

SireneMoewe

Erdapfel
Mitglied seit
02.04.20
Beiträge
5
Das macht Sinn! Danke für die Hilfe und Geduld bei meinen Fragen! Die Fehleingabe hab ich noch nicht gemacht. Ich möchte jetzt im Programm z.B. den BMI berechnen:
Code:
import SwiftUI

struct Beispiel: View {
    
    
    @State var weight: String = ""
    @State var size: String = ""
    
    lazy var weight1 = Float(weight)
    lazy var size1 = Float(size)
    
    @State var BMI: Float = 0.00
    @State var button = false

    private mutating func rechnen() {

        
        if weight1! == 0 && size1! == 0 {
        BMI = weight1! / (size1! * size1!)
    
      }
    }
    

    var body: some View {
        
        VStack {
            
            TextField("Eintippen / weight", text: $weight)
            Text("\(weight)")
        
            
            TextField("Eintippen / size", text: $size)
            Text("\(size)")
        
            Button(action: {self.button.toggle()
                self.rechnen()
            }) {
                Text(/*@START_MENU_TOKEN@*/"Button"/*@END_MENU_TOKEN@*/)
            }

            Text("\(BMI)")
        }
    }
}

struct Beispiel_Previews: PreviewProvider {
    static var previews: some View {
        Beispiel()
    }
}
Dann gibts aber wieder einen Error wenn die Funktion "rechnen" aufgerufen werden soll. "'self' is immutable" heißt es.. Hab aber so das Gefühl, dass da einiges nicht ganz richtig ist. Wie kann ich denn den BMI vom Programm berechnen lassen?