如何在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
相关产品推荐
相关产品推荐

