我了解如何從 JSON API(實際上是我的本地服務器)“獲取”資料,但是我應該如何考慮從僅擁有資料到在視圖中顯示資料的管道?我直覺上想做的是從獲取函式中“回傳”資料,盡管我知道這不是 Swift URL 函式操作的范式。我的想法是,如果我可以“回傳”資料(作為結構),將很容易傳遞到視圖中進行可視化。
示例代碼:
這是獲取的 JSON 的結構以及我想傳遞給視圖的變數型別。
struct User: Codable {
let userID: String
let userName: String
let firstName: String
let lastName: String
let fullName: String
}
我希望 printUser 函式可以回傳而不是列印成功的獲取。
func printUser() {
fetchUser { (res) in
switch res {
case .success(let user):
print(user.userName) // return here?
// I know it won't work, but that's what seems natural
case .failure(let err):
print("Failed to fetch user: ", err)
}
}
}
func fetchUser(completion: @escaping (Result<User, Error>) -> ()) {
let urlString = "http://localhost:4001/user"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, resp, err) in
if let err = err {
completion(.failure(err))
return
}
do {
let user = try JSONDecoder().decode(User.self, from: data!)
completion(.success(user))
} catch let jsonError {
completion(.failure(jsonError))
}
}.resume()
}
將采用用戶結構的示例視圖
struct DisplayUser: View {
var user: User
var body: some View {
Text(user.userID)
Text(user.userName)
Text(user.lastName)
Text(user.firstName)
Text(user.fullName)
}
}
uj5u.com熱心網友回復:
你不能只是“回傳”的原因是你fetchUser是異步的。這意味著它可能會相對立即回傳,或者可能需要很長時間(或根本沒有完成)。因此,您的程式需要準備好應對這種情況。當然,正如您所說,“很容易傳遞到可視化視圖中”,但不幸的是,它不符合實際情況。
你可以做什么(在你的例子)被設定User為可選的-這樣,如果尚未設定,則可以顯示某種加載視圖的,如果它已經被設定(即你的異步函式回傳一個值),您可以顯示它。這看起來像這樣:
class ViewModel : ObservableObject {
@Published var user : User? //could optionally store the entire Result here
func runFetch() {
fetchUser { (res) in
switch res {
case .success(let user):
DispatchQueue.main.async {
self.user = user
}
case .failure(let err):
print("Failed to fetch user: ", err)
//set an error message here? Another @Published variable?
}
}
}
func fetchUser(completion: @escaping (Result<User, Error>) -> ()) {
//...
}
}
struct DisplayUser: View {
@StateObject private var viewModel = ViewModel()
var body: some View {
VStack {
if let user = viewModel.user {
Text(user.userID)
Text(user.userName)
Text(user.lastName)
Text(user.firstName)
Text(user.fullName)
} else {
Text("Loading...")
}
}.onAppear {
viewModel.fetchUser()
}
}
}
注意:如果這是我的程式,我可能會重構異步內容以使用組合,但這是個人偏好問題
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/345146.html
上一篇:何時在可解碼(Swift)中使用CodingKeys
下一篇:異步等待串列詳細資訊
