首页 > 解决方案 > SwiftUI ForEach 循环多个数组

问题描述

我很难弄清楚如何在 SwiftUI 中循环一些 json数据ForEach。我使用https://app.quicktype.io从这里的 URL 获取我的数据结构arrayarray

我正在寻找类FeaturedHeaderViewFeaturedPackageView,它们的标题为“现在很热”和“我们正在使用什么”,其中也包含FeaturedPackageView数据。我的问题是我只循环通过第一个FeaturedHeaderViewFeaturedPackageView重复,我假设每个部分有两个。我的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()
}

标签: jsonswiftui

解决方案


您获得重复的原因是您使用.viewClassand.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


推荐阅读