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")