xcode 与SwiftUI中基于ID号解析JSON数据相关的问题

amrnrhlw  于 2023-01-10  发布在  Swift
关注(0)|答案(1)|浏览(106)

我是SwiftUI的新手,在SwiftUI中解析JSON文件中的数据时遇到了问题。现在,我可以传递JSON文件中的所有数据,但我想根据数据的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"
    }
  ]
}

正如您在JSON文件中所看到的,在我的业务部门部分,我列出了一个数字列表。这些数字是与公司部分中的特定公司相关联的ID号。我希望在contentView中有六个按钮。每个按钮代表一个业务部门。当我单击每个按钮时,它将跳转到CompanyName View。在那里所有的公司都显示了每个业务部门。然而,我能做的和我已经累了是列出所有的公司在公司名称视图。因此,我需要一些帮助。我会给你看不同的文件在我的项目。
CompanyViewModel.swift,其中处理来自json的所有解析:

import Foundation

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

     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 statusOpen = "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
     }
 }

 
 class CompanyViewModel:ObservableObject{
     
      @Published var company_data: [CompanyData] = []
     
     func getUserData(){
         
         guard let url = Bundle.main.url(forResource:"Company", withExtension:"json") else {
             print("Invalid URL")
             return
         }
         
         let task = URLSession.shared.dataTask(with:url){ data, response, error in
             let decoder = JSONDecoder()
             if let data = data {
                 do {
                     let company_data = try decoder.decode(CompanyData.self, from:data)
                     
                      DispatchQueue.main.async{
                          self.company_data = [company_data]
                      }
                    
                     print(company_data.businessSegments)
                     print()
                     print(company_data.companies)
                     print()
                     
                     
                 } catch {
                     print("cannot decode")
                     print(String(data:data, encoding:.utf8) as Any)
                     print(error)
                 }
             }
             
         }
         
         task.resume()
         
         
     }
 }

ContentView.swift

import SwiftUI

struct ContentView: View {
    @StateObject private var companyVM = CompanyViewModel()
    var body: some View {
        NavigationView{
            VStack {
                ForEach(companyVM.company_data,id:\.self){ item in
                    ForEach(item.businessSegments,id:\.self){ segment in
                        /*Text(segment.name)
                         .multilineTextAlignment(.center)
                         .bold()
                         .font(.custom("Montserrat-Bold", size: 24)) */
                        
                        
                        NavigationLink(destination:
                                        CompanyName(segment: segment.name)){
                            Text(segment.name)
                                .frame(width:240,height:50)
                                .bold()
                                .foregroundColor(.white)
                                .background(Color.orange)
                                .clipShape(Capsule())
                         }
                        
                        
                    }
                }
            }
            .padding()
            .onAppear(){
                companyVM.getUserData()
            }
        }
    }
}

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

CompanyName.swift

import SwiftUI

struct CompanyName: View {
    let segment: String
    @StateObject private var companyVM = CompanyViewModel()
    var body: some View {
        NavigationView{
            VStack{
                Text(segment)
                    .multilineTextAlignment(.center)
                    .bold()
                    .font(.custom("Montserrat-Bold", size: 24))
                
                ForEach(companyVM.company_data,id:\.self){ item in
                    ForEach(item.companies,id:\.self){ company in
                        Text(company.name)
                            .multilineTextAlignment(.center)
                            .bold()
                            .font(.custom("Montserrat-Bold", size: 24))
                    }
                }
                
            }.padding()
                .onAppear(){
                    companyVM.getUserData()
                }
        }
    }
}
    struct CompanyName_Previews: PreviewProvider {
        static var previews: some View {
            CompanyName(segment: "Business Segments")
        }
    }
rt4zxlrg

rt4zxlrg1#

下面是显示与所选细分市场相关的公司的代码。当你点击一个细分市场时,该特定细分市场的公司将从以下位置检索(基于ID):特定CompanyData或所有[CompanyData]。调整代码以选择其中一个,两个函数都在CompanyViewModel中提供。
注意,我留下了@Published var company_data: [CompanyData],尽管您说其中只有一个CompanyData
请查看此链接,其中提供了如何使用ObservableObject以及如何在应用https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app中管理数据的示例

class CompanyViewModel: ObservableObject {
    @Published var company_data: [CompanyData] = []
    
    func getUserData(){
        guard let url = Bundle.main.url(forResource:"Company", withExtension:"json") else {
            print("Invalid URL")
            return
        }
        let task = URLSession.shared.dataTask(with:url){ data, response, error in
            let decoder = JSONDecoder()
            if let data = data {
                do {
                    let company_data = try decoder.decode(CompanyData.self, from:data)
                    DispatchQueue.main.async{
                        self.company_data = [company_data]
                    }
                    print(company_data.businessSegments)
                    print()
                    print(company_data.companies)
                    print()
                } catch {
                    print("cannot decode")
                    print(String(data:data, encoding:.utf8) as Any)
                    print(error)
                }
            }
        }
        task.resume()
    }
    
    // get all companies for a particular segment and from a particular CompanyData
    func getCompaniesFor(seg: BusinessSegment, item: CompanyData) -> [BusinessSegment] {
        var companies = [BusinessSegment]()
        if let segCompanies = seg.companies {
            for id in segCompanies {
                for company in item.companies {
                    if company.id == id {
                        companies.append(company)
                    }
                }
            }
        }
        return companies
    }
    
    // get all companies for a particular segment from all [CompanyData]
    func getAllCompaniesFor(seg: BusinessSegment) -> [BusinessSegment] {
        var companies = [BusinessSegment]()
        if let segCompanies = seg.companies {
            company_data.forEach { company_data in
                for company in company_data.companies {
                    for id in segCompanies {
                        if company.id == id {
                            companies.append(company)
                        }
                    }
                }
            }
        }
        return companies
    }
    
}

struct ContentView: View {
    @StateObject var companyVM = CompanyViewModel() // <-- here
    
    var body: some View {
        NavigationView{
            VStack {
                ForEach(companyVM.company_data){ item in
                    ForEach(item.businessSegments){ segment in
                        /*Text(segment.name)
                         .multilineTextAlignment(.center)
                         .bold()
                         .font(.custom("Montserrat-Bold", size: 24)) */
                        
                        // --- here
                        NavigationLink(destination:
                                        CompanyName(segment: segment, companyVM: companyVM)){
                            Text(segment.name)
                                .frame(width:240,height:50)
                                .bold()
                                .foregroundColor(.white)
                                .background(Color.orange)
                                .clipShape(Capsule())
                        }
                    }
                }
            }
            .padding()
            .onAppear {
                companyVM.getUserData()
            }
        }
    }
}

struct CompanyName: View {
    let segment: BusinessSegment  // <-- here
    @ObservedObject var companyVM: CompanyViewModel // <-- here
    
    var body: some View {
        NavigationView{
            VStack{
                Text(segment.name).foregroundColor(.blue)
                    .multilineTextAlignment(.center)
                    .bold()
                    .font(.custom("Montserrat-Bold", size: 24))
                
                // --- here
                ForEach(companyVM.getAllCompaniesFor(seg: segment)){ company in
                    Text(company.name)
                        .multilineTextAlignment(.center)
                        .bold()
                        .font(.custom("Montserrat-Bold", size: 24))
                }
                
            }.padding()
        }
    }
    
}

// MARK: - CompanyData
struct CompanyData: Identifiable, Codable,Hashable { // <-- here
    let id = UUID() // <-- here
    let client: Client
    let businessSegments, companies: [BusinessSegment]
    
    enum CodingKeys: String, CodingKey {
        case client, companies
        case businessSegments = "business_segments"
    }
}

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

// MARK: - Client
struct Client: Identifiable, Codable,Hashable { // <-- here
    let id: Int
    let firstName, lastName, email: String
    
    enum CodingKeys: String, CodingKey {
        case id, email
        case firstName = "first_name"
        case lastName = "last_name"
    }
}

相关问题