我很难弄清楚如何在 SwiftUI 中 ForEach
循环一些 array
的 array
json 数据。我使用 https://app.quicktype.io 从这个 URL here 获取我的数据结构。
我希望获得类 FeaturedHeaderView
和 FeaturedPackageView
,它们的标题为“Hot Right Now”和“What We're Using”,其中还包含 FeaturedPackageView
数据。我的问题是我只重复循环第一个 FeaturedHeaderView
和 FeaturedPackageView
,我假设每个部分有两个。我的 data struct
不正确吗?我从未尝试过复杂的 json 数据,所以我不确定如何正确处理它,以及 ForEach
循环是否是我正在寻找的。最终目标是让 List
带有“现在很热”和它的项目,然后是“我们正在使用的东西”和它的项目。
我能够使用两个 FeaturedBannersView
循环很好地获得 ForEach
类,并认为这对其余数据是相同的方法?
横幅视图工作
ScrollView(.horizontal) {
HStack {
ForEach(self.welcome.views, id: \.viewClass) { views in
ForEach(views.banners ?? [], id:\.url) { banner in
ZStack (alignment: .bottomLeading) {
GeometryReader { geometry in
RequestImage(Url(banner.url), animation: nil)
.aspectRatio(contentMode: .fit)
.frame(width: geometry.size.width)
.clipped()
.cornerRadius(CGFloat(views.itemCornerRadius ?? 0))
}
HStack {
Text(banner.title ?? "")
.fontWeight(.bold)
.font(.title3)
.foregroundColor(Color.white)
}
.padding(.all, 15)
}
.frame(width: 263, height: 148)
}
}
}
.padding(.leading, 10)
.padding(.trailing, 10)
}
问题
我的数据结构
struct Welcome: Codable {
let views: [WelcomeView]
}
struct WelcomeView: Codable {
let viewClass: String?
let banners: [Banner]?
let views: [PurpleView]?
enum CodingKeys: String, CodingKey {
case viewClass = "class"
case views
}
}
struct Banner: Codable {
let url: String?
let title, package, repoName: String?
}
struct PurpleView: Codable {
let viewClass: String?
let views: [FluffyView]
enum CodingKeys: String, CodingKey {
case viewClass = "class"
case views
}
}
struct FluffyView: Codable {
let viewClass: String?
let title: String?
let package, packageName, packageAuthor: String?
let repoName: RepoName?
let packageIcon: String?
enum CodingKeys: String, CodingKey {
case viewClass = "class"
case title, package, packageName, packageAuthor, repoName, packageIcon
}
}
enum RepoName: String, Codable {
case chariz = "Chariz"
case packix = "Packix"
}
List {
ForEach(self.welcome.views, id: \.viewClass) { view in
ForEach(view.views ?? [], id: \.viewClass) { purple in
ForEach(purple.views, id: \.packageName) { fluffy in
if fluffy.viewClass == "FeaturedHeaderView" {
Text(fluffy.title ?? "")
.font(.title3)
.fontWeight(.bold)
} else {
HStack (spacing: 15){
RequestImage(Url(fluffy.packageIcon ?? ""), animation: nil)
.aspectRatio(contentMode: .fit)
.frame(width: 60, height: 60)
.clipped()
.cornerRadius(13.5)
VStack (alignment: .leading){
Text(fluffy.packageName ?? "")
.font(.body)
Text(fluffy.packageAuthor ?? "")
.foregroundColor(Color.secondary)
.font(.callout)
Text(fluffy.repoName?.rawValue ?? "")
.foregroundColor(Color.secondary)
.font(.subheadline)
}
}
}
}
}
}
}
.onAppear() {
request()
}
答案 0 :(得分:1)
您得到重复的原因是您使用 .viewClass
和 .packageName
作为 ForEach
循环的 ID,但在 JSON 中,这些值是 <强>不是实际上是独一无二的。例如,FeaturedStackView
会重复。
将 ID 添加到您的模型并将其用于 ForEach
键。
// MARK: - WelcomeView
struct WelcomeView: Codable {
var id = UUID() //<-- HERE
let viewClass: String
let itemSize: String?
let itemCornerRadius: Int?
let banners: [Banner]?
let horizontalSpacing: Int?
let views: [PurpleView]?
enum CodingKeys: String, CodingKey {
case viewClass = "class"
case itemSize, itemCornerRadius, banners, horizontalSpacing, views
}
}
struct PurpleView: Codable {
var id = UUID()
let viewClass: String
let preferredWidth: Int
let views: [FluffyView]
let xPadding: Int?
enum CodingKeys: String, CodingKey {
case viewClass = "class"
case preferredWidth, views, xPadding
}
}
struct FluffyView: Codable {
var id = UUID()
let viewClass: String
let title: String?
let useBoldText: Bool?
let package, packageName, packageAuthor: String?
let repoName: RepoName?
let packageIcon: String?
let orientation: String?
let views: [TentacledView]?
let text: String?
let action: String?
let yPadding: Int?
enum CodingKeys: String, CodingKey {
case viewClass = "class"
case title, useBoldText, package, packageName, packageAuthor, repoName, packageIcon, orientation, views, text, action, yPadding
}
}
然后,在每个 ForEach
循环中,使用 id: \.id