将经过筛选的@Bindable对象传递到SwiftUI中的多个视图

时间:2019-08-12 01:32:28

标签: swift filter swiftui bindable

我正在尝试将过滤器数组传递给多个视图,但过滤器无法正常工作。如果删除筛选器,则可以将数组传递到下一个视图,但这会在ForEach循环期间导致另一个错误。我已经在下面发布了所有代码。

有人知道如何传递@Bindable数组的过滤器版本吗?另外为什么我不能在ForEach循环中打印sport.name和sport.isFavorite.description?

我在Xcode 11.0 beta 5上使用swiftUI。

import SwiftUI
import Combine

struct Sport: Identifiable{
    var id = UUID()
    var name : String
    var isFavorite = false
}

final class SportData: ObservableObject  {
    @Published var store =
        [
            Sport(name: "soccer",   isFavorite: false),
            Sport(name: "tennis",   isFavorite: false),
            Sport(name: "swimming", isFavorite: true),
            Sport(name: "running",  isFavorite: true)
    ]
}

struct Testing: View {
    @ObservedObject var sports = SportData()

    var body: some View {
        VStack {
            TestingTwo(sports: $sports.store.filter({$0.isFavorite}))
        }
    }
}

struct TestingTwo: View {
    @Binding var sports : [Sport]

    var body: some View {t
        NavigationView {
            VStack(spacing: 10){
                ForEach($sports) { sport in
                    NavigationLink(destination: TestingThree(sport: sport)){
                        HStack {
                            Text(sport.name)
                            Spacer()
                            Text(sport.isFavorite.description)
                        }
                        .padding(.horizontal)
                        .frame(width: 200, height: 50)
                        .background(Color.blue)
                    }
                }
            }
        }
    }
}

struct TestingThree: View {
    @Binding var sport : Sport

    var body: some View {
        VStack {
            Text(sport.isFavorite.description)
                .onTapGesture {
                    self.sport.isFavorite.toggle()
            }
        }
    }
}


#if DEBUG
struct Testing_Previews: PreviewProvider {
    static var previews: some View {
        Testing()
    }
}
#endif

2 个答案:

答案 0 :(得分:1)

由于您的绑定要求,在您的情况下进行过滤可能会更好地放在导航视图中。

struct Testing: View {
    @ObservedObject var sports = SportData()

    var body: some View {
        VStack {
            TestingTwo(sports: $sports.store)
        }
    }
}

struct TestingTwo: View {
    @Binding var sports : [Sport]
    @State var onlyFavorites = false

    var body: some View {t
        NavigationView {
            VStack(spacing: 10){
                ForEach($sports) { sport in
                    if !self.onlyFavorites || sport.value.isFavorite {
                        NavigationLink(destination: TestingThree(sport: sport)){
                            HStack {
                                Text(sport.value.name)
                                Spacer()
                                Text(sport.value.isFavorite.description)
                            }
                            .padding(.horizontal)
                            .frame(width: 200, height: 50)
                            .background(Color.blue)
                        }
                    }
                }
            }
        }
    }
}

现在,您可以在按钮的动作实现内或指定isFavorite视图的集成时切换TestingTwo状态。

struct Testing: View {
    @ObservedObject var sports = SportData()

    var body: some View {
        VStack {
            TestingTwo(sports: $sports.store, onlyFavorites: true)
        }
    }
}

关于问题的第二部分:请注意value循环中的ForEach附录。您在此处处理的是绑定(如ForEach($sports)所示),因此sport不是Sport的实例。

答案 1 :(得分:1)

由于计算的属性是动态计算的,因此无法从计算的属性获取@Binding。避免这种情况的一种典型方法是传递运动对象的ID和数据存储本身,从而可以从存储中通过ID访问运动项目。

如果您确实要传递@Binding,则必须删除过滤器(传递实际支持的数组),并像下面这样修改ForEach

  ForEach($sports.store) { (sport: Binding<Sport>) in