【问题标题】:SwiftUI is it possible to pass range of binding in ForEach?SwiftUI 是否可以在 ForEach 中传递绑定范围?
【发布时间】:2021-03-06 12:59:33
【问题描述】:

我想在 ForEach 内部的模型中传递一个数组范围。

我重新创建了一个示例:

import SwiftUI

class TheModel: ObservableObject {
    @Published var list: [Int] = [1,2,3,4,5,6,7,8,9,10]
}

struct MainView: View {
    @StateObject var model = TheModel()
    var body: some View {
        VStack {
            ForEach (0...1, id:\.self) { item in
                SubView(subList: $model.list[0..<5])  <-- error if I put a range                    
            }
        }
    }
}

struct SubView: View {
    @Binding var subList: [Int]
    var body: some View {
        HStack {
            ForEach (subList, id:\.self) { item in
                Text("\(item)")
            }
        }
    }
}

struct MainView_Previews: PreviewProvider {
    static var previews: some View {
        MainView()
    }
}

变通方法

我发现是传递所有列表并执行子视图内的范围。但我不想这样做,因为数组非常大:

struct MainView: View {
@StateObject var model = TheModel()
var body: some View {
    VStack {
        ForEach (0...1, id:\.self) { i in
            SubView(subList: $model.list, number: i, dimension: 5)
        }
    }
}
}

struct SubView: View {
    @Binding var subList: [Int]
    var number: Int
    var dimension: Int
    
    var body: some View {
        HStack {
            ForEach (subList[number*dimension..<dimension*(number+1)].indices, id:\.self) { idx in
                Button(action: {
                    subList[idx] += 1
                    print(subList)
                }, label: {
                    Text("num: \(subList[idx])")
                })
                
            }
            
        }
    }
}

【问题讨论】:

  • 为什么SubView.subList 是一个绑定? SubView 可以以某种方式更改给它的数组,并且您希望更改反映在 TheModel.list 中吗?
  • @Sweeper 是的,在解决方法中,我插入了一个按钮,例如更改项目的示例
  • 哦,对了。我没有过多阅读您的解决方法代码,并认为它们是相同的,哈哈
  • 请注意,您不能通过从list[0..&lt;5] 获得的ArraySlice 改变原始数组,即使没有这些 SwiftUI 的东西。所以我的想法是编写你自己的引用类型来包装一个数组,你可以将它传递给子视图,而这次不需要复制整个数组。
  • @Sweeper 你能用代码写出你的想法吗? :)

标签: ios swift swiftui


【解决方案1】:

我会将模型传递给子视图,因为它是一个类,将通过引用传递,然后将范围作为单独的参数传递。

这是我对 SubView 的新实现

struct SubView: View {
    var model: TheModel
    var range: Range<Int>
    var body: some View {
        HStack {
            ForEach (model.list[range].indices, id:\.self) { idx in
                HStack {
                    Button(action: {
                        model.list[idx] += 1
                        print(model.list)
                    }, label: {
                        Text("num: \(model.list[idx])")
                    })
                }
            }
        }
    }
}

请注意,我在ForEach 标头中添加了indices,以确保我们使用索引而不是数组中的值访问数组。

调用视图看起来像

var body: some View {
    VStack {
        SubView(model: model, range: (0..<5))
        Text("\(model.list.map(String.init).joined(separator: "-"))")
    }

额外的Text 仅用于测试目的

【讨论】:

  • 所以没办法只传递数组的一部分?
  • 你可以,但是你必须有代码来更新模型中的数组进行更改,我看不出这会更简单
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-27
  • 1970-01-01
  • 2021-01-29
  • 2010-09-15
  • 1970-01-01
  • 2012-11-03
相关资源
最近更新 更多