有没有办法将变量/布尔值带入View的SuperView?

时间:2019-09-20 03:44:24

标签: swift swiftui

假设我将以下sudocode作为名为Item的视图

Item{
  Rectangle()
   .frame(width: 100, height: 50)
   .onTapGesture{
     isTapped.toggle()
   }
}

在其超级视图中有多个项目,内容

Content{
  VStack{
    Item()
    Item()
    Item()
  }
}

我是否有办法从Item传递变量/布尔值 isTapped ,直到它仍然是Item特定的,才成为其超级视图? (所以我知道哪个项目具有 isTapped 值),例如,这可能吗?...

Content{
  VStack{
    Item().padding(.bottom, Item.isTapped ? 20 : 0)
    Item().padding(.bottom, Item.isTapped ? 20 : 0)
    Item().padding(.bottom, Item.isTapped ? 20 : 0)
  }
}

编辑:一个关键的细节是,项目的数量将由用户动态生成,因此,例如,我无法为每个项目创建一个变量

2 个答案:

答案 0 :(得分:0)

在父级中将变量声明为@State,并将其作为@Binding传递给子级。

答案 1 :(得分:0)

可能的解决方案是:

首先定义“真相来源”模型

import SwiftUI
import Combine
import Foundation

enum itemType{
  case itemTypeA
  case itemTypeB
  case itemTypeC
}

struct ItemModel: Identifiable  {
  var id: Int
  var type: itemType
  var isTapped: Bool = false
}

class ObserverModel: ObservableObject {
  var didChange = PassthroughSubject<Void, Never>()

  @Published var itemA: ItemModel = ItemModel(id: 1, type: .itemTypeA)
  @Published var itemB: ItemModel = ItemModel(id: 2, type: .itemTypeB)
  @Published var itemC: ItemModel = ItemModel(id: 3, type: .itemTypeC)

  func toggleItem(itemType: itemType) {
    switch itemType {
    case .itemTypeA:
      itemA.isTapped.toggle()
    case .itemTypeB:
      itemB.isTapped.toggle()
    case .itemTypeC:
      itemC.isTapped.toggle()
    }
  }
}

您的单个​​ItemView应该看起来像这样:

import SwiftUI

struct ItemView: View {
  @EnvironmentObject var observer: ObserverModel
  @Binding var itemBinding: ItemModel
  @State private var toggleColor = Color.red

  var body: some View {
    Rectangle()
      .fill(toggleColor)
      .frame(width: 100, height: 50)
      .onTapGesture{
        self.observer.toggleItem(itemType: self.itemBinding.type)
        self.toggleColor = self.itemBinding.isTapped ? Color.green : Color.red

        print("Item Bool: \(self.itemBinding.isTapped)")
    }
  }
}

struct ItemView_Previews: PreviewProvider {
  static var previews: some View {
    ItemView(itemBinding: .constant(ItemModel(id: 1, type: .itemTypeA))).environmentObject(ObserverModel())
  }
}

最后,您将所有内容放在一起:

import SwiftUI

struct ItemsView: View {
  @EnvironmentObject var observer: ObserverModel

    var body: some View {
      HStack {
        ItemView(itemBinding: $observer.itemA)
        ItemView(itemBinding: $observer.itemB)
        ItemView(itemBinding: $observer.itemC)
      }
    }
}

struct ItemsView_Previews: PreviewProvider {
    static var previews: some View {
      ItemsView().environmentObject(ObserverModel())
    }
}

我将此上传到github:https://github.com/ppoh71/SwiftUIButtonTest (内置GM2)

我会推荐这个视频,介绍SwiftUI中的数据流。 这应该可以解释所有内容:https://developer.apple.com/videos/play/wwdc2019/226/

enter image description here