#ios #swift #swiftui
Вопрос:
Я пытаюсь использовать .id(_:)
программную прокрутку с помощью ForEach, чтобы форма прокручивалась каждый раз, когда в нее добавляется новый раздел с помощью ForEach. Тем не менее, я получаю некоторое нежелательное поведение, и мне хотелось бы понять механику того, что вызывает указанное поведение. Как вы можете видеть на скриншоте, третье текстовое представление даже не отображается. Когда я удаляю id
метод, все три вида текста отображаются так, как вы и ожидали.
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) } } } } } } }
Любая помощь будет очень признательна! Ваше здоровье.
Ответ №1:
У вас здесь происходит пара проблем. Я никогда не пытался поместить a Section
внутри a ForEach
, как это, но они, очевидно, плохо играют. Я удалил его и использовал VStack
вместо этого. Я не уверен, сможете ли вы создать такие новые разделы, но это еще один вопрос на другой день.
Проблема, с которой вы ScrollTo
столкнулись, — это непонимание того, что id
вы на самом деле использовали. Когда вы создаете экземпляр a ForEach
с массивом, который иначе не идентифицируется, вы используете .self
в качестве id
. Однако это означает, что вы отслеживаете сами элементы, а не содержимое каждого элемента. Итак, когда вы попытались вставить an int
в свой scrollTo()
, ничего не произошло, потому что an 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) } } } } } } }
Комментарии:
1. Я ценю ответ Yrb. Я потратил много времени, обдумывая ваш комментарий… На самом деле я не думаю, что то, о чем вы упомянули, было проблемой. Я снова посмотрел на свой код и допустил небольшую математическую ошибку с аргументом, в который я ввел
scrollTo
; это должен был быть просто счет. После того, как я это исправил, он начал работать, хотя, как вы упомянули, создание разделов внутри поForEach
-прежнему вызывает проблему. Еще раз спасибо за ответ.
Ответ №2:
На всякий случай, если кто-нибудь случайно прочтет это, после множества экспериментов я смог заставить это работать. Похоже , что проблема, которую я опубликовал на своих скриншотах, была вызвана созданием разделов внутри ForEach
, как уже упоминалось, Yrb. Тем не менее, я попробовал другой инициализатор для создания разделов, и, похоже, он работает до тех пор, пока вы предоставляете представление для заголовка раздела. Я понятия не имею, почему, однако, если у кого-то есть какие-либо идеи, пожалуйста, поделитесь ими.
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)") } } } }