为什么我的 Swift 网络请求不起作用? [英] Why aren't my Swift network requests working?
问题描述
我是第一次尝试 Swift/SwiftUI,所以我决定制作一个小型的 Hacker News 客户端.我似乎能够很好地恢复头条新闻的 id 列表,但是一旦 dispatchGroup
参与进来,什么都不起作用.我做错了什么?
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
(可能无关紧要,但以防万一)
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()
}
}
推荐答案
通过调用 Fetch().getStories,Fetch
类会立即超出范围并且不会保留.
By calling Fetch().getStories, the Fetch
class goes out of scope immediately and isn't retained.
我建议将 Fetch
设为 ObservableObject
并将其设置为您视图上的属性:
I'd recommend making Fetch
an ObservableObject
and setting it as a property on your view:
@StateObject var fetcher = Fetch()
然后,调用:
fetcher.getStories {
self.stories = stories
}
如果您想使用它获得更多 SwiftUI 风格,您可能需要查看 ObservableObject
上的 @Published
属性以及如何让您的视图做出响应自动给他们.通过这样做,您可以完全避免在您的视图中使用 @State
变量,不必有回调函数,而只需将故事加载到 @Published
ObservableObject 上的属性.当 @Published
属性更改时,您的视图将重新呈现.更多阅读:https://www.hackingwithswift.com/quick-start/swiftui/observable-objects-environment-objects-and-published
If you wanted to get even more SwiftUI-ish with it, you may want to look into @Published
properties on ObservableObject
s and how you can make your view respond to them automatically. By doing this, you could avoid having a @State
variable on your view at all, not have to have a callback function, and instead just load the stories into a @Published
property on the ObservableObject. Your view will be re-rendered when the @Published
property changes. More reading: https://www.hackingwithswift.com/quick-start/swiftui/observable-objects-environment-objects-and-published
这篇关于为什么我的 Swift 网络请求不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!