【问题标题】:Trying to understand how .id(_:) works in SwiftUI试图了解 .id(_:) 在 SwiftUI 中的工作原理
【发布时间】:2021-11-19 02:50:06
【问题描述】:

我正在尝试使用.id(_:) 使用 ForEach 进行一些程序化滚动,这样每次使用 ForEach 将新部分添加到表单时都会滚动表单。但是,我遇到了一些不良行为,我想了解导致所述行为的机制。正如您在屏幕截图中看到的那样,第三个文本视图甚至没有出现。当我删除 id 方法时,所有三个 Text 视图都会按您的预期显示。

import SwiftUI

struct ContentView: View {
    @State private var array: [Int] = [1]
    var body: some View {
        ScrollViewReader { p in
            NavigationView {
            Form {
                ForEach(self.array, id: \.self) { num in
                    Section {
                        Text("Hello")
                        Text("My name is slim shady")
                        Text("number \(num)")
                    }
                    .id(num)
                    .onChange(of: array.count) { count in
                        p.scrollTo((count + 1), anchor: .top)
                    }
                }
            }
            .toolbar {
                ToolbarItem(placement: .bottomBar) {
                    Button("add") {
                        array.append(array.count + 1)
                    }
                }
            }
            }
        }
    }
}

任何帮助将不胜感激!干杯。

【问题讨论】:

    标签: ios swift swiftui


    【解决方案1】:

    这里有几个问题。我从来没有尝试像这样将Section 放在ForEach 中,但它们显然玩得不好。我将其删除并改用VStack。我不确定你是否可以制作这样的新部分,但这是另一天的问题。

    您遇到的ScrollTo 问题是对您实际使用的id 的误解。当您使用无法以其他方式识别的数组实例化ForEach 时,您使用.self 作为id。但是,这意味着您要跟踪元素本身,而不是每个元素的内容。因此,当您尝试将int 放入您的scrollTo() 时,什么都没有发生,因为int 不是您的数组的元素。您需要做的是提供这样的元素:

    struct ContentView: View {
        @State private var array: [Int] = [1]
        var body: some View {
            ScrollViewReader { p in
                NavigationView {
                    Form {
                        ForEach(self.array, id: \.self) { num in
                            VStack(alignment: .leading) {
                                Text("Hello")
                                Text("My name is slim shady")
                                Text("number \(num)")
                            }
                            // num is an element of your array, not an int
                            .id(num)
                            .onChange(of: array.count) { count in
                                // Supply scrollTo with an array element here
                                p.scrollTo(array.last, anchor: .top)
                            }
                        }
                    }
                    .toolbar {
                        ToolbarItem(placement: .bottomBar) {
                            Button("add") {
                                array.append(array.count + 1)
                            }
                        }
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 感谢 Yrb 的回复。我花了很多时间考虑你的评论......我实际上并不认为你提到的是问题。我再次查看了我的代码,我在传递给scrollTo 的参数中犯了一个小数学错误;它应该只是被计数。在我修复它之后,它开始工作,尽管正如你提到的在 ForEach 内创建部分仍然会导致问题。再次感谢您的回复。
    【解决方案2】:

    以防万一有人碰巧读到这篇文章,经过一堆实验,我已经能够完成这项工作。正如 Yrb 提到的,我在屏幕截图中发布的问题似乎是由在 ForEach 内创建部分引起的。但是,我尝试了不同的初始化程序来创建节,只要您为节标题提供视图,它似乎就可以工作。但是我不知道为什么,如果有人有任何见解,请分享。

    struct ContentView: View {
        @State private var array: [Int] = [1]
        var body: some View {
            ScrollViewReader { p in
                NavigationView {
                    Form {
                        ForEach(self.array, id: \Int.self) { num in
                            Section {
                                TextVeiwshg(num: num)
                            } header: {
                                Text("section #\(num)")
                            }
                            .id(num)
                        }
                    }
                    .toolbar {
                        ToolbarItem(placement: .bottomBar) {
                            Button("add") {
                                array.append(array.count + 1)
                                print(array)
                            }
                        }
                    }
                }
                .onChange(of: array.count) { count in
                    print(array.count)
                    withAnimation {
                        p.scrollTo((count), anchor: .top)
                    }
                    print("scrolling to \(count)")
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-20
      • 1970-01-01
      • 1970-01-01
      • 2018-06-23
      • 1970-01-01
      相关资源
      最近更新 更多