我想用 SwiftUI 將以下 JSON 決議成一個串列,但是我遇到了一些問題。
JSON(以隨機識別符號作為條目的整體比這多得多。這就是導致它更難執行的原因):
{
"DCqkboGRytms": {
"name": "graffiti-brush-3.zip",
"downloads": "5",
"views": "9",
"sha256": "767427c70401d43da30bc6d148412c31a13babacda27caf4ceca490813ccd42e"
},
"gIisYkxYSzO3": {
"name": "twitch.png",
"downloads": "19",
"views": "173",
"sha256": "aa2a86e7f8f5056428d810feb7b6de107adefb4bf1d71a4ce28897792582b75f"
},
"bcfa82": {
"name": "PPSSPP.ipa",
"downloads": "7",
"views": "14",
"sha256": "f8b752adf21be6c79dae5b80f5b6176f383b130438e81b49c54af8926bce47fe"
}
}
SwiftUI 可編碼:
struct Feed: Codable {
let list: [FeedValue]
}
struct FeedValue: Codable, Identifiable {
var id = UUID()
let name, downloads, views, sha256: String
}
JSON Fetch 方法(和決議):
func getFeeds(completion:@escaping (Feed) -> ()) {
// URL hidden to respect API privacy
guard let url = URL(string: "") else { return }
URLSession.shared.dataTask(with: url) { (data, _, _) in
let feed = try! JSONDecoder().decode(Feed.self, from: data!)
DispatchQueue.main.async {
completion(feed)
}
}.resume()
}
最后,包含我的 ForEach 回圈的視圖:
struct HomeView: View {
@State private var scrollViewContentOffset: CGFloat = .zero
@State var listFeed = Feed(list: [])
var body: some View {
// Z-coord status bar holder
ZStack(alignment: .top) {
TrackableScrollView(.vertical, showIndicators: true, contentOffset: $scrollViewContentOffset) {
// Public files Start
LazyVStack(spacing: 0) { {
// Withholds our content for each asset retrieved.
// Main part
ForEach(listFeed.list, id: \.id) { download in
AssetView(name: .constant(download.name), downloads: .constant(download.downloads), views: .constant(download.views))
}
}.padding([.leading, .top, .trailing], 25)
// Public files End
}.edgesIgnoringSafeArea([.leading, .trailing, .top])
}.background(Color.backgroundColor.ignoresSafeArea())
.onAppear() {
getFeeds { feed in
//print(feed) : this did happen to work at the time of testing
self.listFeed = feed
}
}
}
}
對于出現的錯誤:
Starfiles/HomeView.swift:32:致命錯誤:“嘗試!” 運算式意外引發錯誤:Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "list", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: "list ", intValue: nil) ("list").", 基礎錯誤: nil))
我今天花了幾個小時更改決議方法,但無法自己找到解決方案。
編輯 1:我想提一下,我還需要一種訪問字典 ID 的方法,因為它們將用于輸入新視圖。
編輯 2:使用 @jnpdx 提供的內容,JSON 決議現在可以按預期作業,并獲得我需要的資訊。但是,ForEach 回圈存在問題,與之前一直存在的回圈相同(正如他的回答所示,它確實在 List() 中作業)。
這是更新的代碼(不會顯示任何不相關的代碼)
ForEach(listItems) { item in // Cannot convert value of type '[IdentifiableFeedValue]' to expected argument type 'Binding<C>' & Generic parameter 'C' could not be inferred
AssetView(name: .constant(item.feedValue.name), // Cannot convert value of type 'Binding<Subject>' to expected argument type 'String'
downloads: .constant(item.feedValue.downloads), views: .constant(item.feedValue.views))
}.onAppear() {
// URL hidden to respect API privacy, refer to JSON above.
guard let url = URL(string: "") else { return }
URLSession.shared.dataTask(with: url) { (data, _, _) in
do {
list = try JSONDecoder().decode([String:FeedValue].self, from: data!)
} catch {
print("error")
}
}.resume()
}
// AssetView
struct AssetView: View {
@Binding var name: String
@Binding var downloads: String
@Binding var views: String
...
}
uj5u.com熱心網友回復:
您的 JSON 沒有任何名為 的鍵list
,這就是它失敗的原因。因為它是一個動態鍵控字典,所以您需要將其解碼為[String:FeedValue]
.
我使用了一個包裝器來保留id
原始 JSON,但如果你想將它保持在一個級別struct
,你也可以做一些更高級的解碼,但這超出了這個問題的范圍。
let jsonData = """
{
"DCqkboGRytms": {
"name": "graffiti-brush-3.zip",
"downloads": "5",
"views": "9",
"sha256": "767427c70401d43da30bc6d148412c31a13babacda27caf4ceca490813ccd42e"
},
"gIisYkxYSzO3": {
"name": "twitch.png",
"downloads": "19",
"views": "173",
"sha256": "aa2a86e7f8f5056428d810feb7b6de107adefb4bf1d71a4ce28897792582b75f"
},
"bcfa82": {
"name": "PPSSPP.ipa",
"downloads": "7",
"views": "14",
"sha256": "f8b752adf21be6c79dae5b80f5b6176f383b130438e81b49c54af8926bce47fe"
}
}
""".data(using: .utf8)!
struct FeedValue: Codable {
let name, downloads, views, sha256: String
}
struct IdentifiableFeedValue : Identifiable {
let id: String
let feedValue: FeedValue
}
struct ContentView: View {
@State var list : [String:FeedValue] = [:]
var listItems: [IdentifiableFeedValue] {
list.map { IdentifiableFeedValue(id: $0.key, feedValue: $0.value) }
}
var body: some View {
List(listItems) { item in
Text(item.feedValue.name)
}.onAppear {
do {
list = try JSONDecoder().decode([String:FeedValue].self, from: jsonData)
} catch {
print(error)
}
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/470113.html
上一篇:在API中存盤傳入資料的數量