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

SwiftUI中如何基于API导入数据创建动态Picker

动态加载API数据实现SwiftUI Picker选择器方案

我从API获取数据,没办法给Picker用枚举或者静态列表。折腾了一阵没找到现成方案,这里分享我的实现思路。

  • 使用.task{}发起服务器请求,获取Season数组
  • 用户在Picker中选择Season后,通过.onChange()将本地保存的seasonNumber设置为选中Season的id,后续选球队时会用到这个id
  • 第二个.onChange()是临时处理方案:本来打算直接在.task{}里给seasons赋值,但它会在leagueDataModel.league.seasons!完成赋值前执行,导致seasons一直为空,必须离开页面再返回才会更新。如果有更优实现欢迎留言讨论。

视图代码(TeamSelectView)

import SwiftUI

struct TeamSelectView: View {
    @StateObject private var leagueDataModel = LeagueDataModel()
    @State private var teamSeason = Season()
    @State private var seasons : [Season] = []
    @State private var seasonNumber = "1"
    var url = "fakeurl.com"
    var body: some View {
        VStack{
            Picker("Season", selection:  $teamSeason){
                ForEach(seasons, id: \.self) {
                    Text($0.name!).tag($0.id)
                }
            }
            ForEach(leagueDataModel.league.teamsNoAll!) { each in
                TeamCard(team: each, season: seasonNumber)
            }
        }
        
        .task{
            await self.leagueDataModel.getLeagueData(url: url)
        }
        
        .onChange(of: self.teamSeason) {
            self.seasonNumber = teamSeason.id ?? "1"
        }
         
        .onChange(of: self.leagueDataModel.league.seasons) {
            seasons = leagueDataModel.league.seasons!
        }
    }

}

数据模型类(LeagueDataModel)

import Foundation
import SwiftUI

@MainActor
class LeagueDataModel : ObservableObject {
 
    @Published var league = League()
    
    func getLeagueData(url: String) async {
        Service().getDataFromServer(stringurl: url) { (data : League) in
                    DispatchQueue.main.async { [self] in
                        self.league = data
                }
        }
    }

}

数据结构定义(League & Season)

// MARK: - League
struct League: Codable {
    var seasons: [Season]? = []
}

// MARK: - Season
class Season: Codable, Hashable {
    // seasons包含id(1、2、3等)和名称(2024季后赛、2024季前赛等)
    let id, name: String?


    enum CodingKeys: String, CodingKey {
        case id, name
    }
    
// 所有字段必须设为可选类型,这样才能初始化空的Season实例
// 也可以给字段设默认值,但我更倾向这种方式
    init(id: String? = nil, name: String? = nil) {
        self.id = id
        self.name = name
    }
    // Picker需要Season实现Hashable协议
    func hash(into hasher: inout Hasher) {
        hasher.combine(id)

    }
    static func == (lhs: Season, rhs: Season) -> Bool {
        return lhs.id == rhs.id
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 05:08:28