SwiftUI GeometryReader загружает свой контент дважды

Как дела?

Обратите внимание на следующий код:

struct ContentView: View {

   var body: some View {

      NavigationView {
          GeometryReader { geometry in
              ZStack(alignment: .leading) {
                  ViewOne()
                     .frame(height: geometry.size.height / 2)
              }
          }
      }
   }
}

struct ViewOne: View {

   init() {
       print("View one init")
   }

   var body: some View {
       VStack(alignment: .center) {
           Text("This is View one")
               .font(.system(size: 50))
       }
   }
}

Мой вопрос прост: почему ViewOne создается два раза внутри GeometryReader и только один раз за пределами GeometryReader?

Сначала я подумал, что представление нужно создать один раз, а затем второй раз, учитывая размеры GeometryReader, однако, если у вас есть более сложный контент в ViewOne, все становится беспорядочно.

Есть идеи??

Спасибо за ваше время и помощь в этом SwiftUI, друзья!!

1 ответ

Это не из-за GeometryReader(рассмотрите вариант ниже или вставьте в любой xStack), это потому, что все помещено вNavigationView, который составляет собственную сложную планировку. Более того, вы не рассчитываете, сколько разView.init называется - View - это структура, значение, его можно создавать / копировать много раз во время макета и рендеринга представлений (Apple обещала сделать его оптимальным, но это все).

Так что просто не кладите ничего тяжелого (несвязанного) в View.init(и вообще во View). Используйте для этого другие шаблоны проектирования.

struct TestGeometryReaderBuilder: View {

   var body: some View {
          GeometryReader { geometry in
              ZStack(alignment: .leading) {
                  ViewOne()
                    .frame(height: geometry.size.height / 2)
              }
          }
    }
}

struct ViewOne: View {

   init() {
       print("ViewOne> init")
   }

   var body: some View {
       print("ViewOne> build")
       return VStack(alignment: .center) {
           Text("This is View one")
               .font(.system(size: 50))
       }
   }
}

Другие вопросы по тегам