4

Why does TvAiringTodayView init 2 times when "TV" is clicked on the tab bar? Sometimes it only loads once, but mostly happens every time. I get the following output when I run the app and click on the "TV" tab bar button:

initMainView
initMovieMainView
initTvMainView
initTvButtonBarView
initTvAiringTodayView
initTvAiringTodayView

You may have to try it twice to see it happen. It doesn't seem like the TvAiringTodayView should init twice when clicked, but it does.

import SwiftUI

struct ContentView: View {

    var body: some View {
        TabView {
            //Movies View
            MovieMainView()
                .tabItem {
                    Image(systemName: "film")
                    Text("Movies")
            }

            //TV View
            TvMainView()
                .tabItem {
                    Image(systemName: "tv")
                    Text("TV")
            }            
        }
    }

    init() {
        print("initMainView")
    }
}

struct MovieMainView: View {

    var body: some View {
        VStack {
            Text("MovieMainView")
        }
    }

    init() {
        print("initMovieMainView")
    }
}

struct TvMainView: View {

    var body: some View {
        VStack {
            ScrollView(.vertical, showsIndicators: false) {
                TvButtonBarView()
            }
        }
    }

    init() {
        print("initTvMainView")
    }
}

struct TvButtonBarView: View {
    @State private var selectedViewType = 0
    var viewType = ["On The Air", "Top Rated", "Popular"]

    var body: some View {
        VStack {
            Picker(selection: $selectedViewType, label: Text("Strength")) {
                ForEach(0 ..< viewType.count ) {
                    Text(self.viewType[$0])
                }
            }.pickerStyle(SegmentedPickerStyle())

            if selectedViewType == 0 {
                TvAiringTodayView()
            }
            //            if selectedViewType == 1 {
            //                TvTopRatedView()
            //            }
            //            if selectedViewType == 2 {
            //                TvPopularView()
            //            }
        }
    }

    init() {
        print("initTvButtonBarView")
    }
}

struct TvAiringTodayView: View {

    var body: some View {
        Text("TvAiringTodayView")
    }

    init() {
        print("initTvAiringTodayView")
    }
}
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
JStevison
  • 41
  • 1
  • 2
  • Unless you need to do something meaning full in the `init()`, I would use `.onAppear { }` as it will only perform calls when the view is loaded. – MwcsMac Apr 30 '20 at 19:00
  • `TabView` is the problem. It might need some improvement given that `SwiftUI` is new. I have observed it reloads views that are nested within multiple `Vstack`s. Take a look at this [answer](https://stackoverflow.com/a/58164937/2857130) for a possible solution. – staticVoidMan May 01 '20 at 14:14

1 Answers1

0

I have tested this code for more then 20 time and there were no cases that is mentioned in question. I believe that issue you are facing is some kind of bug.

Unlike classes, structs are easy to create and destroy. Hence, TvAiringTodayView's init is called every time state of parent change. When selectedViewType != 0, the struct is destroyed from cleared from memory and when selectedViewType == 0, the struct is init again. This create multiple init calls when stength picker change state of selectedViewType.

NikzJon
  • 912
  • 7
  • 25