SwiftUI: Wie setze ich den Text im Textfield?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • SwiftUI: Wie setze ich den Text im Textfield?

    Ich habe eine Klasse Login aus der ich das Textfield setzen möchte. Wie mache ich das?

    Dankeschön :)

    Quellcode

    1. import SwiftUI
    2. struct LoginView: View {
    3. @State public var password: String = ""
    4. var body: some View {
    5. VStack(alignment: .center) {
    6. NavigationStack {
    7. TextField("Passwort", text: $password, prompt: Text("Passwort"))
    8. .frame(width: 200, height: 40)
    9. .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
    10. .cornerRadius(15)
    11. .background(Color(UIColor.systemGray5))
    12. .disableAutocorrection(true)
    13. NavigationLink("Anmelden", value: "Home")
    14. .navigationDestination(for: String.self) { textValue in
    15. HomeView()
    16. }
    17. .navigationTitle("Willkommen bei Denkste!")
    18. }
    19. }
    20. .onAppear() {
    21. let database = Database()
    22. database.delegate = Login()
    23. database.DownloadAllUsers()
    24. }
    25. }
    26. }
    27. class Login: DatabaseProtocol {
    28. func allUsersDownloaded() {
    29. LoginView().password = "Hallo". // <<<< Das funktioniert nicht!!
    30. print("Ready")
    31. return
    32. }
    33. }
    Alles anzeigen
  • Ich mache das immer so:

    Quellcode

    1. struct LoginView: View {
    2. @State public var password: String = ""
    3. // Hier das init rein und die Übergabewerte den States zuordnen
    4. init(password: String) {
    5. _password = State(initialValue: password)
    6. }
    7. var body: some View {
    8. VStack(alignment: .center) {
    9. NavigationStack {
    10. TextField("Passwort", text: $password, prompt: Text("Passwort"))
    11. .frame(width: 200, height: 40)
    12. .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
    13. .cornerRadius(15)
    14. .background(Color(UIColor.systemGray5))
    15. .disableAutocorrection(true)
    16. NavigationLink("Anmelden", value: "Home")
    17. .navigationDestination(for: String.self) { textValue in
    18. HomeView()
    19. }
    20. .navigationTitle("Willkommen bei Denkste!")
    21. }
    22. }
    23. .onAppear() {
    24. let database = Database()
    25. database.delegate = Login()
    26. database.DownloadAllUsers()
    27. }
    28. }
    29. }
    30. class Login: DatabaseProtocol {
    31. func allUsersDownloaded() {
    32. // hier den Parameter angeben.
    33. LoginView(password = "Hallo")
    34. print("Ready")
    35. return
    36. }
    37. }
    Alles anzeigen

    Wenn du den Wert aus dem subView wieder zurück im MainView brauchst, musst du mit Bindings arbeiten. Das geht dann so


    Quellcode

    1. struct LoginView: View {
    2. @Binding public var password: String
    3. // Hier das init rein und die Übergabewerte den States zuordnen
    4. init(password: Binding<String>) {
    5. _password = password
    6. }
    7. [...]
    8. }
    9. class Login: DatabaseProtocol {
    10. func allUsersDownloaded() {
    11. // hier den Parameter angeben.
    12. LoginView(password = "Hallo")
    13. print("Ready")
    14. return
    15. }
    16. }
    Alles anzeigen
  • Ich Danke Dir, Ich blicke insgesamt leider noch nicht ganz durch. Ich habe es wie folgt geändert. Aber Der Wert "Hallo" wird nicht ins Textfeld übergeben.

    Quellcode

    1. import SwiftUI
    2. struct LoginView: View {
    3. @State public var password: String
    4. init(password: String) {
    5. _password = State(initialValue: password)
    6. }
    7. var body: some View {
    8. VStack() {
    9. NavigationStack {
    10. TextField("Passwort", text: $password, prompt: Text("Passwort"))
    11. .frame(width: 200, height: 40)
    12. .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
    13. .cornerRadius(15)
    14. .background(Color(UIColor.systemGray5))
    15. .disableAutocorrection(true)
    16. NavigationLink("Anmelden", value: "Home")
    17. .navigationDestination(for: String.self) { textValue in
    18. HomeView()
    19. }
    20. .navigationTitle("Willkommen!")
    21. }
    22. }
    23. .onAppear() {
    24. let database = Database()
    25. database.delegate = Login()
    26. database.DownloadAllUsers()
    27. }
    28. }
    29. }
    30. class Login: DatabaseProtocol {
    31. func allUsersDownloaded() {
    32. LoginView(password: "Hallo")
    33. print("Ready")
    34. return
    35. }
    36. }
    Alles anzeigen

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Dirk86 ()

  • Also die Grundstruktur ist ja so....

    Quellcode

    1. @State private var username : String = ""
    2. HStack{
    3. Text("Username")
    4. TextField("Enter username", text: $username)
    5. }

    (Alignments lasse ich an dieser Stelle mal weg)

    Oder mit Prompts


    Quellcode

    1. @State private var username : String = ""
    2. @State private var password : String = ""
    3. Form {
    4. TextField(text: $username, prompt: Text("Enter Username")) {
    5. Text("Username")
    6. }
    7. SecureField(text: $password, prompt: Text("Enter password")) {
    8. Text("Enter Password")
    9. }
    (Passwörter kannst du im übrigen als SecureField angeben, dann wird die Eingabe nicht als Text angezeigt)


    In deinem Fall würde ich die Variable in der du Hallo setzen willst, einfach mit dem .onAppear identifier auf "hallo" setzen, denn du brauchst sie ja nur wenn du auf die View aufspringst und würde das nicht so kompliziert mit Übergabeparameter machen.
    Und gerade für die Loginseite, die du ja vermutlich nur ein mal zu beginn siehst, würde ich die einfachste Lösung anpeilen. :)
  • Da hast du natürlich Recht, aber ich versuche mich gerade etwas in SwiftUI einzuarbeiten. Ich muss nicht hier aber an anderer Stelle geladene Daten aus einer Datenbank in die Textfelder schreiben.

    Mit dem Storyboard habe ich einfach in meiner Klasse Login.text = "Hallo" gesetzt.

    Hier scheint alles sehr kompliziert. Blicke mit den @Binding, @State... noch nicht ganz durch.

    Warum wird im Code das Textfield auf BBBB gesetzt, nicht aber auf AAAA???

    Quellcode

    1. import SwiftUI
    2. struct LoginView: View {
    3. @State public var password: String
    4. init(passwd: String) {
    5. self.password = passwd
    6. }
    7. var body: some View {
    8. VStack() {
    9. NavigationStack {
    10. TextField("", text: $password)
    11. .frame(width: 200, height: 40)
    12. .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
    13. .cornerRadius(15)
    14. .background(Color(UIColor.systemGray5))
    15. .disableAutocorrection(true)
    16. Button("Drück mich") {
    17. self.password = "Grrrr"
    18. }
    19. NavigationLink("Anmelden", value: "Home")
    20. .navigationDestination(for: String.self) { textValue in
    21. HomeView(name: "Dirk")
    22. }
    23. .navigationTitle("Willkommen!")
    24. }
    25. }
    26. .onAppear() {
    27. // BBBB wird im Textfield gesetzt!!!
    28. self.password = "BBBB"
    29. let database = Database()
    30. database.delegate = Login()
    31. database.DownloadAllUsers()
    32. }
    33. }
    34. }
    35. class Login: DatabaseProtocol {
    36. func allUsersDownloaded() {
    37. // WARUM WIRD AAAA nicht im Textfield gesetzt????
    38. LoginView.init(passwd: "AAAA")
    39. print("Ready")
    40. return
    41. }
    42. }
    Alles anzeigen

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von Dirk86 ()

  • Ganz einfach, weil Du den wert AAAA im onAppear mit BBBB überschreibst. AAAA gibt es dann nicht mehr, wenn die View angezeigt wird.

    Du kannst es dir auch einfach machen. Erstelle einfach eine Klasse "Brain". Die nimmst dann in der Hauptroutine in das Environment. Dann kannst du aus jeder View auf die Klasse zugreifen. Das ist dann deine Source-of-thruth. Da schreibst dann einfach deine Variablen rein, ggf. auch noch mit der Logik und fertig. Das ganze ergänzt du dann noch mit @Observable Macro (neu in SwiftUI 5) und du hast kein Problem mehr.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Wolf ()

  • Nur mal so gaaaaanz banal erklärt (so merke ich es mir zumindest so grob)

    @State-Variable: ist eine "Status-Variable". Die prüft permanent in dem View, ob sich in der Variable eine Änderung ergibt. Jede Änderung der Variable wird so auch an alle Stellen im View übertragen. Diese gehört allein diesem View und sonst keinem.
    @Binding: damit erstellt man eine Art "Tunnel" zwischen Haupt-View und Sub-View. Das Binding funktioniert in etwa so wie zwei verschränkte Quanten: was in dem einen View geändert wird, wird auch in dem anderen View geändert. Darum müssen den ViewItems wie Text, TextField, DatePicker etc. auch immer ein Binding übergeben werden, damit Änderungen dort auch wieder im View übernommen werden können.

    Wie gesagt: gaaaanz einfach. Natürlich ist das unter der Motorhaube etwas komplizierter.

    Wenn ich Funktionen über mehrere Views hinweg brauche, dann erstelle ich die func in einer View-Extension.

    Quellcode

    1. extension View {
    2. func allUsersDownloaded(passwd: Binding<String>) {
    3. passwd = "Yo Man!"
    4. }
    5. }


    Wenn du die eine func nur in dem einen View brauchst, dann erstelle die einfach im View, den du erstellt hast.


    Quellcode

    1. struct LoginView: View {
    2. [...]
    3. func allUsersDownload() {
    4. passwd = "Yes, Sir!"
    5. }
    6. }

    Um da mal einen guten Einstieg zu bekommen, mach mal das Tut durch:
    youtube.com/watch?v=YIZxSZJMU2…JTkn9KxHzYeSRqUbQ&index=1
  • @mihema: Dankeschön. Wenn ich die Funktion in den struct View packe, wie rufe ich Sie dann auf?

    ich hab ja nen Delegate drauf von der Database Class.


    Quellcode

    1. let database = Database()
    2. database.delegate = self
    3. database.DownloadAllUsers()

    Das funktioniert dann ja nicht! Die Funktion allUsersDownloaded() wird ja aus der class Database aus per Delegate aufgerufen.

    Offtopic: QM ist mir ehlichgesagt klarer als dieses Chaos hier :) Danke für die Erklärung


    EDIT: HABS HINBEKOMMEN!!! DANKESCHÖN!!!!

    Freue mich gerade riesig :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Dirk86 ()

  • Hier noch ein Beispiel, kurz runtergeschrieben ohne Compiler... sollte aber funktionieren..

    Quellcode

    1. import SwiftUI
    2. @Observable final class Brain {
    3. var isLoggedIn: Bool = false
    4. func logOut() {
    5. isLoggedIn = false
    6. }
    7. func logMeIn(username: String, passwd: String) {
    8. if usernameAndPassWdOk(username: username, passwd: passwd) {
    9. isLoggedIn = true
    10. }
    11. }
    12. private func UsernameAndPassWdOk(username: String, passwd: String) -> Bool {
    13. //prüf was du willst
    14. // wenn in Ordnung
    15. return true
    16. }
    17. }
    18. @main
    19. struct MySuperApp: App {
    20. @State private var brain = Brain()
    21. var body: some Scene {
    22. WindowGroup {
    23. ContentView()
    24. .environmentObject(brain)
    25. }
    26. }
    27. }
    28. struct ContentView: View {
    29. @EnvironmentObject private var brain: Brain
    30. var body: some View {
    31. if brain.isLoggedIn {
    32. VLogOut()
    33. } else {
    34. VLogIn()
    35. }
    36. }
    37. }
    38. struct VLogIn() {
    39. @EnvironmentObject private var brain: Brain
    40. @State private var uName: String = ""
    41. @State private var passWd: String = ""
    42. var body: some View {
    43. @Bindable var brain = brain //wird nicht benötigt, da über Funktion geprüft wird
    44. VStack {
    45. TextField("Username: ", $uName)
    46. TextField("PassWd: ", $passWd)
    47. Button {
    48. brain.logMeIn(username: uName, passwd: passWd)
    49. } label: {
    50. Text("Login")
    51. }
    52. }
    53. }
    54. }
    55. struct VLogOut() {
    56. @EnvironmentObject private var brain: Brain
    57. var body: some View {
    58. Button {
    59. brain.logOut()
    60. } label: {
    61. Text("Logout")
    62. }
    63. }
    64. }
    Alles anzeigen
    Hat den Vorteil, dass "Brain" überall verfügbar ist, und durch @Observable alle Änderungen durchgereicht werden, genau zu der View, die neu gezeichnet werden soll.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Wolf ()

  • Hallo Manoh,

    ist mir klar. Mir ging es um den prinzipiellen Aufbau und die Weitergabe der Variablen. Habe auch dazu geschrieben, dass ich derzeit keine Compiler im Zugriff habe. Habe auch gezeigt, dass man mit @Bindable auch bei einem Let/Var noch Bindings erstellen kann, wenn man diese benötigen sollte.
    Für Profis wie dich, ziemlich uninteressant, aber für Dirk86 vielleicht der Schlüssel für weitere Lösungen.,

    Schöne Grüsse
    Wolf
  • Wolf schrieb:

    Hallo Manoh,

    ist mir klar.
    Meine Antwort war nicht an dich gerichtet. Sondern allgemein.

    Wenn es an dich gerichtet wäre, dann hätte ich dich auch namentlich erwähnt.

    Wolf schrieb:

    Für Profis wie dich, ziemlich uninteressant
    Nop. Bin definitiv kein SwiftUI Profi. Alles andere als ein SwiftUI-Profi. Aber k.A., manche Dinge kennt man einfach bzw. hat eine Erwartungshaltung, die es dann auch irgendwie gibt. Darum ist mir das gleich eingefallen und wollte nur Senf dazugeben.

    Wäre ich ein Profi, dann wüste ich wie man die Passwortabfrage gleich mit dem Schlüsselbund verbindet. Aber keine Ahnung wie das geht. Das kannst Du mir ja dann erklären @Wolf