TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

SOLVED: URLSession and LoadingView

Forums > SwiftUI

@Kdkwn  

Hey,

i created a simple method to fetch products from a API:

class ViewModel: ObservableObject {

    @Published var product: Product?
    @Published var isErrorAppearing: Bool = false
    @Published var errorMessage: String = ""
    @Published var isLoading: Bool = false

    func getProductByBarCode(barcode: String) async {
        DispatchQueue.main.async {
            self.isLoading = true
        }

        guard let url = URL(string: "") else {
            self.isErrorAppearing = true
            self.errorMessage = ""
            return
        }

        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            let decoded = try JSONDecoder().decode(CompleteProduct.self, from: data)

            DispatchQueue.main.async {
                self.product = decoded.product
                self.isLoading = false
            }
        } catch {
            DispatchQueue.main.async {
                self.isErrorAppearing = true
                self.errorMessage = ""
            }
        }
    }
}

My problem is now, I created this inside a view model, and publish the product when I get it from the API.

I am relativ new to Swift and have some questions to this.

  1. How I can create a LoadingView when I call the Method to fetch the products? I want to have a custom LoadingView thst appears when a buttons get pressed in the HomeView as long the data has appers I want to switch the View from the LoadingView to another View, where the data is displayed.

  2. Next question is, how can I handle the errors better or is that a good way how I did that here?

Thank you really much for your help!

2      

Couple of things Let the View handle which Loading to do based on the data. So ViewModel is this

class ViewModel: ObservableObject {
    @Published var product: Product?
    @Published var showingAlert: Bool = false
    @Published var errorMessage: String = ""

    func getProductByBarCode(barcode: String) async {
        guard let url = URL(string: barcode) else {
            showingAlert = true
            errorMessage = "Unable to get URL"
            return
        }

        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            let decoded = try JSONDecoder().decode(CompleteProduct.self, from: data)

            product = decoded.product
        } catch {
            showingAlert = true
            errorMessage = "Unable to decode data!"
        }
    }
}

and the View

struct ContentView: View {
    @StateObject var viewModel = ViewModel()
    let barCode = "Some URL"

    var body: some View {
        VStack {
            if let product = viewModel.product { // will only show when it has data
                Text(product.name)
            } else {
                ProgressView() // Used built in loading view but you can make your own
            }
        }
        .padding()
        .alert("Error", isPresented: $viewModel.showingAlert) { } message: { Text(viewModel.errorMessage) }
        .task { await viewModel.getProductByBarCode(barcode: barCode) }
    }
}

PS just used simple structs for the model

struct Product: Identifiable, Codable {
    var id = UUID()
    var name: String
}

struct CompleteProduct: Codable {
    let product: Product
}

2      

@Kdkwn  

Thank you very much! :)

2      

Hacking with Swift is sponsored by RevenueCat.

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.