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

Problem with GCD

Forums > SwiftUI

I write my project in SwiftUI with VIPER pattern, and i stucked a little bit with this problem. You can see that i call a function of presenter in a view when list appear. This function calls function of interactor and in this function calling service function. The problem is that service don't have time to return data and interactors function returns empty array. How to order code execution using GCD in such order : service function -> interactor function -> presenter function. Thanks in advance !

class PunkApiService:ObservableObject{

    @Published var beers = [Beer]()

    func loadList(at page: Int) {
        //MARK: - Checks is URL is valid + pagination
        guard let url = URL(string: "https://api.punkapi.com/v2/beers?page=\(page)&per_page=25") else {
            print("Invalid URL")
            return
        }
        //MARK: - Creating URLSession DataTask
        let task = URLSession.shared.dataTask(with: url){ data, response, error in
            //MARK: - Handling no erros came
            guard error == nil else {
                print(error!)
                return
            }
            //MARK: - Handling data came
            guard let data = data else{
                print("Failed to load data")
                return
            }
            //MARK: - Decoding data
            do{
                let beers = try JSONDecoder().decode([Beer].self, from: data)
                //MARK: - Puting this piece of code to the main thread to update view when data is decoded
                DispatchQueue.main.async {
                    self.beers.append(contentsOf: beers)
                }
            }
            catch{
                print("Failed to decode data")
            }
        }
        task.resume()
        print(beers)
    }
}
class BeersListInteractor:BeersListInteractorProtocol{

    private var favoriteBeers = FavoriteBeers()
    private var service  = PunkApiService()

    //MARK: - Load list of Beers
    func loadList(at page: Int) -> [Beer]{
        service.loadList(at: page)
        return service.beers
    }
class BeersListPresenter: BeersListPresenterProtocol, ObservableObject{
    var interactor: BeersListInteractorProtocol

    init(interactor: BeersListInteractorProtocol){
        self.interactor = interactor

    }

    @Published var beers = [Beer]()

    func loadList(at page: Int) {
        self.beers = interactor.loadList(at: page)
    }
}
struct BeersListView: View{
    @StateObject var presenter : BeersListPresenter

    var body: some View {
        NavigationView{
            List{
                ForEach(presenter.beers, id: \.id){ beer in
                    Text(beer.name)
                }
            }.onAppear{
                presenter.loadList(at: 1)
            }
        }
    }
}

2      

Are you developing for the latest platforms in Xcode 13, because in WWDC21 Apple presented try await for the Async\Await combination?

Maybe that can help you.

I cannot help you with the details as I have not yet used try await myself.

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.