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

SwiftUI中如何基于业务段ID关联解析对应公司JSON数据?

SwiftUI JSON解析与业务段关联公司展示问题

我是SwiftUI新手,目前已能读取完整JSON数据,但需要实现以下功能:在ContentView中生成对应6个业务段的按钮,点击按钮跳转至CompanyName View,仅展示该业务段关联ID对应的公司(而非全部公司)。附上相关文件代码寻求解决方案。

JSON文件内容

{  
  "client": {    
    "id": 200,    
    "first_name": "Luke",    
    "last_name": "",    
    "email": "luke@abc.com"  
  },  
  "business_segments": [    
    {      
      "id": 1,      
      "name": "Segment A",      
      "status": "Open",      
      "companies": [5,6,7]    
    },    
    {      
      "id": 2,      
      "name": "Segment B",      
      "status": "Open",      
      "companies": [1,2,4]    
    },    
    {      
      "id": 3,      
      "name": "Segment C",      
      "status": "Open",      
      "companies": [3,8,12]    
    },    
    {      
      "id": 4,      
      "name": "Segment D",      
      "status": "Open",      
      "companies": [9,10,15]    
    },    
    {      
      "id": 5,      
      "name": "Segment E",      
      "status": "Open",      
      "companies": [11,13,14,16]    
    },    
    {      
      "id": 6,      
      "name": "Segment F",      
      "status": "Open",      
      "companies": [17,18]    
    }  
  ],  
  "companies": [    
    {      
      "id": 1,      
      "name": "COMPANY A",      
      "status": "Open"    
    },    
    {      
      "id": 2,      
      "name": "COMPANY B",      
      "status": "Open"    
    },    
    {      
      "id": 3,      
      "name": "COMPANY C",      
      "status": "Open"    
    },    
    {      
      "id": 4,      
      "name": "COMPANY D",      
      "status": "Open"    
    },    
    {      
      "id": 5,      
      "name": "COMPANY E",      
      "status": "Open"    
    },    
    {      
      "id": 6,      
      "name": "COMPANY F",      
      "status": "Open"    
    },    
    {      
      "id": 7,      
      "name": "COMPANY G",      
      "status": "Open"    
    },    
    {      
      "id": 8,      
      "name": "COMPANY H",      
      "status": "Open"    
    },    
    {      
      "id": 9,      
      "name": "COMPANY I",      
      "status": "Open"    
    },    
    {      
      "id": 10,      
      "name": "COMPANY J",      
      "status": "Open"    
    },    
    {      
      "id": 11,      
      "name": "COMPANY K",      
      "status": "Open"    
    },    
    {      
      "id": 12,      
      "name": "COMPANY L",      
      "status": "Open"    
    },    
    {      
      "id": 13,      
      "name": "COMPANY M",      
      "status": "Open"    
    },    
    {      
      "id": 14,      
      "name": "COMPANY N",      
      "status": "Open"    
    },    
    {      
      "id": 15,      
      "name": "COMPANY O",      
      "status": "Open"    
    },    
    {      
      "id": 16,      
      "name": "COMPANY P",      
      "status": "Open"    
    },    
    {      
      "id": 17,      
      "name": "COMPANY Q",      
      "status": "Open"    
    },    
    {      
      "id": 18,      
      "name": "COMPANY R",      
      "status": "Open"    
    }  
  ]
}

CompanyViewModel.swift代码

import Foundation

// MARK: - CompanyData
struct CompanyData: Codable, Hashable {
    let client: Client
    let businessSegments: [BusinessSegment]
    let companies: [Company]

    enum CodingKeys: String, CodingKey {
        case client
        case businessSegments = "business_segments"
        case companies
    }
}

// MARK: - BusinessSegment
struct BusinessSegment: Codable, Hashable {
    let id: Int
    let name: String
    let status: Status
    let companies: [Int]?
}

enum Status: String, Codable {
    case open = "Open"
}

// MARK: - Client
struct Client: Codable, Hashable {
    let id: Int
    let firstName, lastName, email: String

    enum CodingKeys: String, CodingKey {
        case id
        case firstName = "first_name"
        case lastName = "last_name"
        case email
    }
}

// 匹配JSON的公司结构体
struct Company: Codable, Hashable {
    let id: Int
    let name: String
    let status: Status
}

class CompanyViewModel: ObservableObject{
    @Published var companyData: CompanyData?

    func getUserData(){
        guard let url = Bundle.main.url(forResource:"Company", withExtension:"json") else {
            print("无效URL")
            return
        }

        let task = URLSession.shared.dataTask(with:url){ data, response, error in
            let decoder = JSONDecoder()
            if let data = data {
                do {
                    let companyData = try decoder.decode(CompanyData.self, from:data)
                    DispatchQueue.main.async{
                        self.companyData = companyData
                    }
                } catch {
                    print("解析失败: \(error)")
                    print(String(data:data, encoding:.utf8) ?? "无法打印数据")
                }
            }
        }
        task.resume()
    }

    // 根据业务段过滤对应公司
    func getCompaniesForSegment(_ segment: BusinessSegment) -> [Company] {
        guard let allCompanies = companyData?.companies, let segmentCompanyIds = segment.companies else {
            return []
        }
        return allCompanies.filter { segmentCompanyIds.contains($0.id) }
    }
}

ContentView.swift代码

import SwiftUI

struct ContentView: View {
    @StateObject private var companyVM = CompanyViewModel()
    var body: some View {
        NavigationStack {
            VStack(spacing: 16) {
                if let companyData = companyVM.companyData {
                    ForEach(companyData.businessSegments, id: \.id) { segment in
                        NavigationLink(destination: CompanyName(segment: segment, companyVM: companyVM)) {
                            Text(segment.name)
                                .frame(width:240,height:50)
                                .bold()
                                .foregroundColor(.white)
                                .background(Color.orange)
                                .clipShape(Capsule())
                        }
                    }
                } else {
                    ProgressView("加载中...")
                }
            }
            .padding()
            .onAppear(){
                companyVM.getUserData()
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

CompanyName.swift代码

import SwiftUI

struct CompanyName: View {
    let segment: BusinessSegment
    @ObservedObject var companyVM: CompanyViewModel
    var body: some View {
        NavigationStack {
            VStack(spacing: 16) {
                Text(segment.name)
                    .multilineTextAlignment(.center)
                    .bold()
                    .font(.custom("Montserrat-Bold", size: 24))

                let filteredCompanies = companyVM.getCompaniesForSegment(segment)
                if filteredCompanies.isEmpty {
                    Text("暂无关联公司")
                        .font(.title3)
                        .foregroundColor(.gray)
                } else {
                    ForEach(filteredCompanies, id: \.id) { company in
                        Text(company.name)
                            .multilineTextAlignment(.center)
                            .bold()
                            .font(.custom("Montserrat-Bold", size: 20))
                            .padding(.vertical, 8)
                    }
                }
            }
            .padding()
            .navigationTitle("关联公司")
        }
    }
}

struct CompanyName_Previews: PreviewProvider {
    static var previews: some View {
        let testSegment = BusinessSegment(id: 1, name: "Segment A", status: .open, companies: [5,6,7])
        let vm = CompanyViewModel()
        vm.companyData = CompanyData(client: Client(id: 200, firstName: "Luke", lastName: "", email: "luke@abc.com"),
                                     businessSegments: [testSegment],
                                     companies: [Company(id:5, name: "COMPANY E", status: .open),
                                                 Company(id:6, name: "COMPANY F", status: .open),
                                                 Company(id:7, name: "COMPANY G", status: .open)])
        return CompanyName(segment: testSegment, companyVM: vm)
    }
}

关键修改说明

  1. 修复数据模型错误:原CompanyData中companies类型错误,新增Company结构体匹配JSON字段,保证解析正确性。
  2. 优化ViewModel结构:将company_data从数组改为单个可选对象,新增业务段公司过滤方法,直接复用已加载的数据。
  3. 统一ViewModel实例:CompanyName接收ContentView传递的ViewModel,避免重复加载JSON,保证数据一致。
  4. 更新导航组件:用NavigationStack替代过时的NavigationView,适配新版iOS系统。
  5. 稳定的列表标识:用对象id作为ForEach的唯一标识,比\.self更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 07:20:39