【问题标题】:Change selection of TabView programatically using Array itself in ForEach SwiftUI在 ForEach SwiftUI 中使用数组本身以编程方式更改 TabView 的选择
【发布时间】:2022-01-15 19:22:27
【问题描述】:

我有一个 TabView,其中我有一个 ForEach 循环用于其中的各种项目,我想使用自动更改选择索引的计时器来更改 TabView 项目的选择。我可以使用具有array.indices0..<array.count 的 ForEach 循环来实现它,但是由于使用前面提到的方法是不安全的,所以我想将数组本身简单地传递到 ForEach 循环中,但同时简单地使用数组foreach 循环不会使用计时器或其他编程方式更改所选索引。用户需要手动滚动以更改选择。以下是我尝试过的代码行,谁能指出我做错了什么。

struct ContentView: View {

@State var currentIndex = 0
@State var itemNames = [ItemNames]()
@State var timer: Timer.TimerPublisher = Timer.publish (every: 6, on: .main, in: .common)


var body: some View {
    TabView(selection: $currentIndex) {
        ForEach(itemNames, id: \.id) { item in
            Text(item.name).tag(Int(item.id))
        }
        }.tabViewStyle(.page(indexDisplayMode: .never))
         .onReceive(timer, perform: {
             _ in withAnimation {
                 currentIndex = currentIndex < itemNames.count ? currentIndex + 1 : 0
             }
         }).onDisappear {
             self.cancelTimer()
         }.onAppear {
             setDemoNames()
             self.instantiateTimer()
             _ = self.timer.connect()
         }
    
}

func instantiateTimer() {
                self.timer = Timer.publish (every: 6, on: .main, in: .common)
                return
}

func cancelTimer() {
                self.timer.connect().cancel()
                return
}

func setDemoNames(){
    let item1 = ItemNames(id: "1", name: "John")
    let item2 = ItemNames(id: "2", name: "Mark")
    let item3 = ItemNames(id: "3", name: "Steve")
    let item4 = ItemNames(id: "4", name: "Peter")
    itemNames = [item1, item2, item3, item4]
}
}


struct ItemNames : Identifiable, Hashable {

  var id:String, name:String;
  init(id: String, name: String) {
      self.id = id
      self.name = name
  }
}

【问题讨论】:

    标签: ios xcode swiftui tabview


    【解决方案1】:

    类型必须完全匹配

    将您的标签更改为

    .tag(Int(item.id) as! Int)
    

    上述行有效,因为它删除了可选/强制。

    您必须确保item.id 始终是有效的Int

    Int(item.id) 产生一个 Int? 类型的值,因为它可能会失败

    你也可以像下面这样不强制,但如果由于某种原因你有 2 个失败的 id,你可能会有重复的标签。

    .tag((Int(item.id) ?? itemNames.count + 1) as Int)
    

    这很容易出现错误,它只适用于非常特定的环境,并且几乎没有后备。

    我会将选择变量切换到 String 并将 tag 与原始 id 保持一致,然后创建一个函数来拉下一个 id 以设置计时器。

    没有强制或可选。

    您也可以通过使用 idInt 而不是 String 来实现此目的

    【讨论】:

    • 选择变量必须等于标签。即使它是整数或字符串,标签和选择变量也必须完全正确,除非它不起作用
    猜你喜欢
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-02
    相关资源
    最近更新 更多