SwiftUI 是不是可以在 ForEach 中传递绑定范围?

Posted

技术标签:

【中文标题】SwiftUI 是不是可以在 ForEach 中传递绑定范围?【英文标题】: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 你能用代码写出你的想法吗? :) 【参考方案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 仅用于测试目的

【讨论】:

所以没办法只传递数组的一部分? 你可以,但是你必须有代码来更新模型中的数组进行更改,我看不出这会更简单

以上是关于SwiftUI 是不是可以在 ForEach 中传递绑定范围?的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 的 List/ForEach 视图中是不是可以有一个 Button(action: -)

ForEach 通过多个 TextField 来验证 SwiftUI 中是不是为空

使用 ForEach (SwiftUI) 的偶数行和奇数行

在 SwiftUI 中,如何在 LinkedList 中“Foreach”节点?

SwiftUI 截断 ForEach 的内容

SwiftUI 在 Foreach 中获得位置