#swiftui #state #swiftui-state
#swiftui #состояние #swiftui-состояние
Вопрос:
Как можно повторно инициализировать представление в SwiftUI, но тело не пересчитывается, а представление повторно отображается?
Пример
import SwiftUI
struct ContentView: View {
var body: some View {
SubView()
.padding()
}
}
struct SubView: View {
@State private var items = [Int]()
init() {
print("SubView init")
}
var body: some View {
Text("(items.count)")
Button("Add item") { items.append(Int.random(in: 0..<10)) }
Divider()
SubSubView()
SubSubView()
}
}
struct SubSubView: View {
init() {
print("SubSubView init")
}
var body: some View {
Text("I'm a subview") (>> _breakpoint here_)
}
}
Если я нажму 4 раза на кнопку, вид будет следующим:
Но у нас есть это в консоли:
SubView init (>> app launch)
SubSubView init (>> app launch)
SubSubView init (>> app launch)
SubSubView init
SubSubView init
SubSubView init
SubSubView init
SubSubView init
SubSubView init
SubSubView init
SubSubView init
body
Свойство SubSubView не пересчитывается (с использованием точки останова).
Является ли это подчиненное представление повторно отображаемым только при наличии каких-либо изменений в зависимости представления, даже если оно повторно инициализируется снова?
Комментарии:
1. Это оптимизация средства визуализации SwiftUI — она создает значение представления (поскольку оно является struct ), но повторно отображает его (вызывая body), только если с момента последнего рисования произошли некоторые изменения.
2. Было бы более полезно, если бы вы могли рассказать нам, почему вам нужно повторно инициализировать представление, поскольку я не думаю, что это возможно, или, по крайней мере, не рекомендуется принудительно повторно отображать в SwiftUI
3. @thisIsTheFoxe на самом деле я больше пытался понять, как различаются жизненные циклы между структурой и представлением. А также для понимания того, когда и почему свойства из
SubView
(например, ViewModel) были повторно инициализированы при повторном отображении contentView (например, если я предоставляю пользовательский Init() для aView
, тогда свойство, вероятно, повторно инициализируется, за исключением случаев, когда я использую оболочку@StateObject
свойств).
Ответ №1:
Итак, я не эксперт и у меня нет никаких источников для этого, но я мог бы представить это примерно так:
При изменении items
переменной SwiftUI должен выяснить, какие подвиды зависят от этого значения, чтобы их можно было повторно отобразить с правильными (обновленными) значениями. Один из простых способов узнать, изменился ли объект, — это использовать хэши. Итак, я думаю, что SwiftUI (внутренне) повторно инициализирует представление, вычисляет хэш над структурой, и если он отличается от хэша текущего представления, он повторно отображается. В противном случае изменение (of items
) не повлияло на представление, поэтому его не нужно повторно отображать.
РЕДАКТИРОВАТЬ: для ясности вычисляемое свойство (например body
) не инициализируется, когда инициализируется остальная часть объекта. Оно вычисляется по требованию. Вот почему вы также можете использовать в них другие переменные.