title: How can I hide and unhide views in SwiftUI with proper onAppear and onDisappear and keep state?
body: <p>I am trying to hide and unhide views in SwiftUI, but it seems quite difficult. I am not able to keep a continuation of state when I'm hiding and unhiding my views.</p>
  <pre class="lang-swift prettyprint-override"><code>struct CounterView: View {
      var title: String
      var delay = 0.5
      
      @State var ticker: Int = 0
      @State var visible = IsVisible()
      
      class IsVisible {
          var bool: Bool = false
      }
      
      var body: some View {
          Text(&quot;\(title) \(ticker)&quot;)
              .onAppear {
                  print(&quot;\(title) onAppear&quot;)
                  if !self.visible.bool {
                      self.visible.bool = true
                      startCounter()
                  }
              }
              .onDisappear {
                  print(&quot;\(title) onDisappear&quot;)
                  self.visible.bool = false
              }
      }
      
      func startCounter() {
          self.ticker += 1
          print(self.ticker)
          
          if self.visible.bool {
              DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
                  self.startCounter()
              }
          }
      }
  }
  
  
  struct ContentView: View {
      @State var hide = false
      
      var body: some View {
          VStack {
              VStack {
                  Button {
                      self.hide.toggle()
                  } label: {
                      Text(hide ? &quot;Show&quot; : &quot;Hide&quot;)
                  }
                  myView()
              }
          }
      }
      
      @ViewBuilder
      func myView() -&gt; some View {
          let view = CounterView(title: &quot;Test&quot;, delay: 0.1)
          if hide {
              view.hidden()
          } else {
              view
          }
      }
  }
  </code></pre>
  <p><strong>Steps to reproduce</strong></p>
  <pre><code>1. Open app
  2. Tap hide
  3. Tap show
  </code></pre>
  <p><strong>Expected result</strong></p>
  <pre><code>Counter continues from last number When the view is hidden it gets no accidental onAppear callbacks
  </code></pre>
  <p><strong>Actual result</strong></p>
  <pre><code>Counter restarts from 0
  When hiding the view a new view is created and it gets an onAppear callback
  </code></pre>
  <p><strong>Wanted solution</strong></p>
  <p>Ideally I would either just do</p>
  <pre class="lang-swift prettyprint-override"><code>let view = CounterView(title: &quot;Test&quot;, delay: 0.1)
  if hide {
      view.hidden()
  } else {
      view
  }
  </code></pre>
  <p>or even better</p>
  <pre class="lang-swift prettyprint-override"><code>CounterView(title: &quot;Test&quot;, delay: 0.1).hide(true)
  </code></pre>