swiftuistatepickerobservedobject

Problem with Picker and @EnvironmentObject - @Published


I'm working on a little application on SwiftUI and I'm struggling for a long while to figure out why when I'm using a SwiftUI Picker, the data source (from the @EnvironmentObject) is well recognized and show the elements correctly, but when I changing the selection from the wheel, the selectedPlayer variable still remains undefined and doesn't show the person's name that I picked.

What I'm missing, please? Thank you for your help!

Here's my source code:

TestApp.swift

@main
struct TestApp: App {
    @StateObject var dataManager = DataManager()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(dataManager)
        }
    }
}

ContentView.swift

struct ContentView: View {
    @EnvironmentObject var dm: DataManager
    @State private var selectedPlayer: Player?
    
    var body: some View {
        VStack {
            Text("Select a player")
                .font(.largeTitle)
                .bold()
                .padding()
            
            Spacer()
            
            Picker("Select Player", selection: $selectedPlayer) {
                ForEach(dm.players) { player in
                    Text(player.name)
                        .tag(player)
                }
            }
            .pickerStyle(.wheel)
            
            VStack(spacing: 10) {
                Text("Selected Player")
                Text(selectedPlayer?.name ?? "Any Player")
                    .font(.headline)
            }
            
            Spacer()
        }
    }
}

DataManager.swift

class DataManager: ObservableObject {
    @Published var players: [Player] = Player.samples
}

Player.swift

struct Player: Identifiable, Hashable, Codable {
    var id = UUID()
    var name: String
    
    static let samples = [Player(name: "Gab"), Player(name: "Ana")]
}

A picture that shows the selection is still undefined, even after changing it


Solution

  • Change your tag to reflect the type of your selectedPlayer

    .tag(player as Player?)
    

    Picker is very specific when it comes to types.