SwiftUI GeometryReader загружает содержимое дважды - PullRequest
1 голос
/ 31 марта 2020

Как дела?

Пожалуйста, рассмотрите следующий код:

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 Ответ

1 голос
/ 31 марта 2020

Это не из-за 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))
       }
   }
}

enter image description here

...