You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SwiftUI嵌套ForEach循环中获取连续索引值?

iOS Widget Extension 2x2网格布局索引错误问题及解决方案

开发Widget Extension时需要实现2行2列的4块网格布局,使用数组元素填充网格,示例数组如下:

let exampleArray = ["test1","test2","test3","test4"]

问题说明

使用两层嵌套ForEach循环实现布局时,无法正确获取第4个索引对应的元素,错误代码如下:

VStack {
    ForEach((0..<2)) { column in
        HStack {
            ForEach((0..<2)) { index in
                ZStack (alignment: .bottomLeading) {
                    Text(newsList[(index+column)])  // 0+0, 1+0, 0+1, 1+1
                    // Text = test1, test2, test2, test3
                }
            }
        }
    }
}

错误原因:index+column的索引计算逻辑错误,得到的索引序列为0、1、1、2,永远取不到索引3对应的第4个元素,导致数组元素重复展示。

完整的错误View代码如下:

struct AppWidgetEntryView : View {
    var entry: Provider.Entry
    
    @Environment(\.widgetFamily)
    var widgetFamily

    var body: some View {
        VStack(alignment: .trailing, spacing: 6) {
            Image("logo")
                .frame(maxWidth: .infinity, alignment: .leading)

            if widgetFamily == .systemLarge {
                VStack {
                ForEach((0..<2)) { column in
                    HStack {
                        ForEach((0..<2)) { index in
                            ZStack (alignment: .bottomLeading) {
                                if let url = URL(string: imageList[(index+column)]), let imageData = try? Data(contentsOf: url),
                                let uiImage = UIImage(data: imageData) {

                                Image(uiImage: uiImage)
                                    .centerCropped()
                                    .frame(maxHeight: 150, alignment: .center)
                                    .cornerRadius(10)
                                            .overlay(RoundedRectangle(cornerRadius: 10)
                                            .stroke(Color.gray, lineWidth: 1))
                                            .shadow(radius: 10)
                                } else {
                                    Image("ph_background")
                                        .centerCropped()
                                        .frame(maxHeight: 150, alignment: .center)
                                        .cornerRadius(10)
                                                .overlay(RoundedRectangle(cornerRadius: 10)
                                                .stroke(Color.gray, lineWidth: 1))
                                                .shadow(radius: 10)
                                }
                                
                                Text(newsList[(index+column)])
                                    .font(.system(size: 12))
                                    .foregroundColor(.white)
                                    .fontWeight(.light)
                                    // .frame(maxHeight: 50)
                                    .background(Rectangle().fill(Color.black).blur(radius: 20))
                                    .padding(.bottom, 5)
                                    .padding(.leading, 5)
                                    .padding(.trailing, 5)
                                    .padding(.top, 5)
                            }
                        }
                    }
                }
            }
        }
    }
}

解决方案

无需嵌套循环,直接使用LazyVGrid实现网格布局,不需要额外运算即可正确获取所有索引的元素,经过验证的实现代码如下:

struct AppWidgetEntryView : View {
    var entry: Provider.Entry
    
    @Environment(\.widgetFamily)
    var widgetFamily

    var body: some View {
        var columns: [GridItem] =
                 Array(repeating: .init(.fixed(100)), count: 2)

        if widgetFamily == .systemLarge {
        LazyVGrid(columns: columns) {
            ForEach((0..<4)) { index in
                ZStack (alignment: .bottomLeading) {
                    if let url = URL(string: imageList[(index)]), let imageData = try? Data(contentsOf: url),
                    let uiImage = UIImage(data: imageData) {

                    Image(uiImage: uiImage)
                        .centerCropped()
                        .frame(maxHeight: 150, alignment: .center)
                        .cornerRadius(10)
                                .overlay(RoundedRectangle(cornerRadius: 10)
                                .stroke(Color.gray, lineWidth: 1))
                                .shadow(radius: 10)
                    } else {
                        Image("ph_background")
                            .centerCropped()
                            .frame(maxHeight: 150, alignment: .center)
                            .cornerRadius(10)
                                    .overlay(RoundedRectangle(cornerRadius: 10)
                                    .stroke(Color.gray, lineWidth: 1))
                                    .shadow(radius: 10)
                    }
                    
                    Text(newsList[(index)])
                        .font(.system(size: 12))
                        .foregroundColor(.white)
                        .fontWeight(.light)
                        // .frame(maxHeight: 50)
                        .background(Rectangle().fill(Color.black).blur(radius: 20))
                        .padding(.bottom, 5)
                        .padding(.leading, 5)
                        .padding(.trailing, 5)
                        .padding(.top, 5)
                }
            }
        }
        }
    }
}

内容的提问来源于stack exchange,提问作者Oguzhan Varsak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 23:15:03