You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI Picker与@EnvironmentObject问题:选中值无法更新

SwiftUI Picker选中值无法更新问题解决

问题描述

Picker可正常识别@EnvironmentObject中的数据源并展示选项,但切换滚轮选择后,selectedPlayer变量始终为nil,无法显示选中的玩家名称。

相关代码

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")]
}

问题根源

WheelPicker的实现逻辑要求绑定的变量具备明确的初始值。当绑定可选类型(Player?)且初始值为nil时,选择操作无法正确将选中的tag值赋值给变量,导致selectedPlayer始终保持nil状态。

解决方案

方案一:给可选类型绑定设置初始值

在视图出现时,将selectedPlayer初始化为数据源的第一个元素:

struct ContentView: View {
    @EnvironmentObject var dm: DataManager
    @State private var selectedPlayer: Player?
    
    var body: some View {
        VStack {
            // 原有视图代码不变
        }
        .onAppear {
            // 安全初始化,避免数据源为空的情况
            selectedPlayer = dm.players.first
        }
    }
}

方案二:使用非可选类型绑定

将selectedPlayer改为非可选类型,确保初始值存在(需保证数据源非空,或做安全处理):

struct ContentView: View {
    @EnvironmentObject var dm: DataManager
    // 直接用数据源的第一个元素初始化,若数据源可能为空需添加判断
    @State private var selectedPlayer: Player = Player.samples.first!
    
    var body: some View {
        VStack {
            // 原有视图代码不变
        }
    }
}

若数据源可能为空,可结合if let做安全处理:

@State private var selectedPlayer: Player? = Player.samples.first

var body: some View {
    VStack {
        // ... 原有代码
    }
    .onAppear {
        selectedPlayer = dm.players.first
    }
}

内容的提问来源于stack exchange,提问作者Gab0111

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 16:20:28