Home > Software design >  Blank Screen on Loading List in SwiftUI
Blank Screen on Loading List in SwiftUI

Time:04-11

I am trying to display a list in a view after a condition. If data is recieved from API than screen will load new view having list showing multiple fields. Here I am showing only one field in the list. The navigation code is working fine and data is also decoded however blank screen appears when clicking list button screen moves to next view but blank screen.

Here is the view in which I am showing list :

      import SwiftUI

       struct MyPriceList: View {

       @StateObject var road = ListAPI()

        List
        {
            ForEach(road.priceRoad)
            {
                road in
                   HStack{
                           Text(road.packageName)
                           .font(.system(size: 15))
                           .foregroundColor(.black)
                         }
             }
         }
     }  
           
       struct MyPriceList_Previews: PreviewProvider {
         static var previews: some View {
             MyPriceList()
                 }
              }
           }

The following is the viewmodel in which I have decoded the JSON data and applied the navigation

    import Foundation

    class ListAPI : ObservableObject
          {
                @Published var priceRoad = [ResponseList]()
            func getList()
                  {
                            // url building code //

               let list = URLSession.shared.dataTask(with: urlRequest)
                  {
                      (data, response, error) in
                       if let error = error {
                            print("Error \(error)")
                           }
        
                   if let data = data
                     {
                               do
                         {
                          let jsonList = try JSONDecoder().decode(PriceList.self, from: data)
                            let panama = jsonList.response
                         for pan in panama
                            {
                               print(pan.packageName) //successfully printing
                            }
                            if jsonList.success==true
                               {
                                   DispatchQueue.main.async
                                        {
                                               self.navigate = true
                                               self.priceRoad = jsonList.response                                    
                                        }
                                }
                    else
                         {
                               DispatchQueue.main.async
                               {
                                   self.errorMessage = jsonList.message
                               }
                          }
                     }
            catch
            {
                print("error \(error)")
            }
        }          
    }
    list.resume()
} }
   

This is the data model for Json

      struct PriceList : Codable
               {
                        let success: Bool
                        let message: String
                        let response: [ResponseList]

                      enum CodingKeys:String, CodingKey{
                                   case response = "ResponseData"
                                   case success = "IsSuccess"
                                   case message = "Message"
                         }
              }


               struct ResponseList:Codable
                    {
                         let packageId: Int
                         let packageName: String
                         let price: Double
                         let discountedPrice: Double
                         let testType: String
                         let testPackageGroupId: Int?
                         let SampleType: [SampleTypeList]?    

                            enum CodingKeys:String, CodingKey{
    
                             case packageId = "PackageId"
                             case packageName = "PackageName"
                             case price = "Price"
                             case discountedPrice = "DiscountedPrice"
                             case testType = "Type"
                             case testPackageGroupId = "TestPackageGroupId"
                             case SampleType = "SampleTypeList"
    }}
   struct SampleTypeList:Codable
                 {
                      let testSampleTypeId: String
                      let sampleName: String
                      let colourCode: String

                             enum CodingKeys:String, CodingKey{
                                case testSampleTypeId = "TestSampleTypeId"
                                case sampleName = "SampleName"
                                case colourCode = "ColourCode"

                               }
                   }

I need to display TestName as packageName, MRP as price, B2B as discountedPrice, and TestType as testType.

CodePudding user response:

try this approach, calling road.getList() in .onAppear{}:

struct MyPriceList: View {
    
    @StateObject var road = ListAPI()
    
    var body: some View {  // <-- here need a body
        List
        {
            ForEach(road.priceRoad)
            {
                road in
                HStack{
                    Text(road.packageName)
                        .font(.system(size: 15))
                        .foregroundColor(.black)
                }
            }
        }
        .onAppear {
            road.getList() // <-- here load your data
        }
    }
}

and make PriceList and ResponseList Identifiable, like this:

struct PriceList : Identifiable, Codable {
    let id = UUID()
    // ...
}

struct ResponseList: Identifiable, Codable {
    let id = UUID()
    // ...
}
    
struct SampleTypeList: Identifiable, Codable {
    let id = UUID()
    // ...
}

Alternatively, in ListAPI, you could have init() { getList() }, instead of using .onAppear {road.getList()}

  • Related