Hallo,
ich versuche gerade eine sehr einfache Liste mit Spielern zu erstellen.
In meinem SplitView werden die einzelnen Spieler in einer Liste angezeigt. Wenn man einen Spieler antippt, gelangt man auf die Detailseite.
Jeder Spieler wird als "struct" aufgerufen und die Liste mit allen Spielern wird in einem "class"-Objekt gehalten.
Es funktioniert auch alles ohne Einwände.
Allerdings möchte ich gerne, dass im Detailview jeweils ein Textfield für den Vornamen und den Nachnamen angezeigt werden. Wenn ich Änderungen im Textfield vornehme, sollen die Änderungen unmittelbar in der Auswahlliste mit allen Spielern sichtbar werden.
Ich habe es mit verschiedenen Formen des Bindings (State, StateObject, etc) probiert. Bin aber kläglich gescheitert.
Vielleicht ist mein Gedankengang auch falsch und Eingaben im Textfield können nicht direkt an die Spieler in der Listenansicht gebunden werden?
Vielleicht passt auch meine Konstruktion mit den struct für Spieler und der class für die Liste nicht?
Über einen "Save"-Button und die direkte Übergabe der eingegebenen Informationen an den ausgewählten Spieler ist es mir gelungen. Ich möchte aber gerne auf den Button verzichten.
Die PlayersList wird als EnvironmentObject behandelt, weil ich die Liste auch in anderen Views der gesamten App benötige.
Vielleicht kann hier jemand einem Anfänger weiterhelfen.
Danke im Voraus.
Alles anzeigen
ich versuche gerade eine sehr einfache Liste mit Spielern zu erstellen.
In meinem SplitView werden die einzelnen Spieler in einer Liste angezeigt. Wenn man einen Spieler antippt, gelangt man auf die Detailseite.
Jeder Spieler wird als "struct" aufgerufen und die Liste mit allen Spielern wird in einem "class"-Objekt gehalten.
Es funktioniert auch alles ohne Einwände.
Allerdings möchte ich gerne, dass im Detailview jeweils ein Textfield für den Vornamen und den Nachnamen angezeigt werden. Wenn ich Änderungen im Textfield vornehme, sollen die Änderungen unmittelbar in der Auswahlliste mit allen Spielern sichtbar werden.
Ich habe es mit verschiedenen Formen des Bindings (State, StateObject, etc) probiert. Bin aber kläglich gescheitert.
Vielleicht ist mein Gedankengang auch falsch und Eingaben im Textfield können nicht direkt an die Spieler in der Listenansicht gebunden werden?
Vielleicht passt auch meine Konstruktion mit den struct für Spieler und der class für die Liste nicht?
Über einen "Save"-Button und die direkte Übergabe der eingegebenen Informationen an den ausgewählten Spieler ist es mir gelungen. Ich möchte aber gerne auf den Button verzichten.
Die PlayersList wird als EnvironmentObject behandelt, weil ich die Liste auch in anderen Views der gesamten App benötige.
Vielleicht kann hier jemand einem Anfänger weiterhelfen.
Danke im Voraus.
Quellcode
- //
- // PlayerData.swift
- import Foundation
- import SwiftUI
- struct Player: Identifiable, Codable, Hashable {
- var id = UUID()
- var firstName: String
- var lastName: String
- }
- @MainActor class PlayersList: ObservableObject {
- @Published var players = [Player]() {
- didSet {
- if let encoded = try? JSONEncoder().encode(players) {
- UserDefaults.standard.set(encoded, forKey: "Players")
- }
- }
- }
- init() {
- if let savedItems = UserDefaults.standard.data(forKey: "Players"){
- if let decodedItems = try? JSONDecoder().decode([Player].self, from: savedItems) {
- players = decodedItems
- return
- }
- }
- players = []
- }
- }
- //
- // PlayerAddView.swift
- //
- import SwiftUI
- struct PlayerAddView: View {
- @EnvironmentObject var playersList: PlayersList
- @Environment(\.dismiss) var dismiss
- @State private var firstName = ""
- @State private var lastName = ""
- var body: some View {
- NavigationStack {
- Form{
- TextField("First Name", text: $firstName)
- TextField("Last Name", text: $lastName)
- }
- .navigationTitle("Add new Player")
- .toolbar{
- Button("Cancel") {
- dismiss()
- }
- Button("Add") {
- let player = Player(firstName: firstName, lastName: lastName)
- playersList.players.append(player)
- dismiss()
- }
- }
- }
- }
- }
- struct PlayerAddView_Previews: PreviewProvider {
- static var previews: some View {
- PlayerAddView()
- .environmentObject(PlayersList())
- }
- }
- //
- // PlayerDetailView.swift
- //
- import SwiftUI
- struct PlayerDetailView: View {
- var player: Player?
- var body: some View {
- if player != nil {
- Text("Hallo \(player!.firstName) \(player!.lastName)")
- // Hier soll ein Textfeld hin, welches z.B. den Vornamen des Spielers beinhaltet. Bei Änderungen im Texrfeld soll die Änderung direkt in der Auswahlliste sichtbar werden, ohne dass man über einen "Save"-Button die Änderung "aktiv" an den Spieler übergibt.
- }
- else {
- VStack {
- Image(systemName: "person.fill")
- Text("Select Player")
- }
- }
- }
- }
- struct PlayerDetailView_Previews: PreviewProvider {
- static var previews: some View {
- PlayerDetailView(player: Player(firstName: "TestVorname", lastName: "TestNachname"))
- }
- }
- //
- // ContentView.swift
- //
- import SwiftUI
- struct ContentView: View {
- @StateObject var playersList = PlayersList()
- @State private var showingAddPlayer = false
- @State private var selectedPlayer: Player?
- var body: some View {
- NavigationSplitView {
- List(selection: $selectedPlayer){
- ForEach(playersList.players) { player in
- NavigationLink("\(player.firstName) \(player.lastName)", value: player)
- }
- .onDelete(perform: removePlayer)
- }
- .navigationTitle("Player")
- .toolbar{
- EditButton()
- Button{
- showingAddPlayer = true
- } label: {
- Image(systemName: "person.badge.plus")
- }
- .sheet(isPresented: $showingAddPlayer) {
- PlayerAddView()
- }
- }
- } detail: {
- PlayerDetailView(player: selectedPlayer)
- }
- .environmentObject(playersList)
- }
- func removePlayer(at offsets: IndexSet) {
- playersList.players.remove(atOffsets: offsets)
- }
- }
- struct ContentView_Previews: PreviewProvider {
- static var previews: some View {
- ContentView()
- .environmentObject(PlayersList())
- }
- }
SwiftUI Newbie