I've been trying out Swift/SwiftUI for the first time, so I decided to make a small Hacker News client. I seem to be able to get the list of ids of the top stories back fine, but once the dispatchGroup
gets involved, nothing works. What am I doing wrong?
Data.swift
import SwiftUI
struct HNStory: Codable, Identifiable {
var id: UInt
var title: String
var score: UInt
}
class Fetch {
func getStory(id: Int, completion: @escaping (HNStory) -> ()) {
let url = URL(string: "https://hacker-news.firebaseio.com/v0/item/\(id).json")
URLSession.shared.dataTask(with: url!) { (data, _, _) in
let story = try!JSONDecoder().decode(HNStory.self, from: data!)
print(id, story)
DispatchQueue.main.async {
completion(story)
}
}
}
func getStories(completion: @escaping ([HNStory]) -> ()) {
let url = URL(string: "https://hacker-news.firebaseio.com/v0/topstories.json")
var stories: [HNStory] = []
print("here")
URLSession.shared.dataTask(with: url!) { (data, _, _) in
var ids = try!JSONDecoder().decode([Int].self, from: data!)
ids = Array(ids[0...10])
print(ids)
let dispatchGroup = DispatchGroup()
for id in ids {
dispatchGroup.enter()
self.getStory(id: id) { (story) in
stories.append(story)
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: .main) {
print("Completed work")
DispatchQueue.main.async {
completion(stories)
}
}
}.resume()
}
}
ContentView.swift
(probably doesn't matter, but just in case)
import SwiftUI
struct ContentView: View {
@State private var stories: [HNStory] = []
var body: some View {
Text("Hacker News").font(.headline)
List(stories) { story in
VStack {
Text(story.title)
Text(story.score.description)
}
}.onAppear{
Fetch().getStories { (stories) in
self.stories = stories
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}