Home > database >  SwiftUI: Waiting for JSON to be decoded before
SwiftUI: Waiting for JSON to be decoded before

Time:01-03

I'm having an issue with displaying a deserialised JSON object in a view. The problem seems to be that my view is trying to unwrap a value from a published variable before anything is assigned to it by the function that gets the JSON object.

Here is the code that calls the api

class ViewModel : ObservableObject {
    
    @Published var posts : first?
    
    init(subReddit : String){
        fetch(sub: subReddit)
    }
    
    func fetch(sub : String) {
        guard let url = URL(string: "https://www.reddit.com/r/"   sub   "/top.json?t=day") else {
            return
        }
        
        let task = URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
                                                            guard let data = data, error == nil else {return}
            do{
                let retVal = try JSONDecoder().decode(first.self, from:data)
                DispatchQueue.main.async {
                    self?.posts = retVal
                }
            }
            catch{
                print(error)
            }
        }
        task.resume()
    }
        
    }

and here is the code for my view:

struct SubRedditView: View {
    @StateObject var viewModel = ViewModel(subReddit: "all")
    var body: some View {
        NavigationView{
            List{
                ForEach((viewModel.posts?.data.children)!) {post in//at runtime I get a nil unwrap error here
                    Text(post.data.title)
                    Text(post.data.url_overridden_by_dest ?? "No Value")
                }
            }
        .navigationTitle("Posts")
    }
}
}

CodePudding user response:

If only the object representing the children is relevant declare the published object as empty array of this type

@Published var posts = [TypeOfChildren]()

Then assign the children to the array

self?.posts = retVal.data.children

This makes the code in the view easier and safe.

 ForEach(viewModel.posts) { post in
        Text(post.title)
        Text(post.url_overridden_by_dest ?? "No Value")
  • Related