2

I'm currently making use UITabBarController in SwiftUI. Here is the implementation:

struct MyTabView: View {

    private var viewControllers: [UIHostingController<AnyView>]

    public init( _ views: [AnyView]) {
        self.viewControllers = views.map { UIHostingController(rootView:$0) }
    }
    
    public var body: some View {
        return TabBarController(controllers: viewControllers)
            .edgesIgnoringSafeArea(.all)
    }

}

struct TabBarController: UIViewControllerRepresentable {

    var controllers: [UIViewController]

    func makeUIViewController(context: Context) -> UITabBarController {
        let tabBarController = UITabBarController()
        tabBarController.viewControllers = controllers
        return tabBarController
    }

    func updateUIViewController(_ tabBarController: UITabBarController, context: Context) { }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, UITabBarControllerDelegate {
        var parent: TabBarController

        init(_ tabBarController: TabBarController) {
            self.parent = tabBarController
        }
    }
}

Inside of my SwiftUI I have the following:

struct ContentView: View {
    var body: some View {

        MyTabView([
            AnyView(Text("Moo Moo")),
            AnyView(MyPage())
        ])

        
    }
}

struct MyPage:View {

    var body:some View {
        
        NavigationView {
            
            VStack {
                ForEach((1...10).reversed(), id: \.self) { value -> AnyView in
                        print("For Each Value Called")
                    return AnyView(MyView(text: String(value)))
                }
            }
            
            
        }
    }
    
}

struct MyView:View {
 
    let text:String

    var body:some View {
        Text(text).onAppear {
            print("On Appear Called - Making Service Call for \(text)")
        }
    }
    
}

I have the following questions:

  1. When running this code the On Appear Called - Making Service Call for \(text), is called twice. What would cause this? My expectation is that it is only run once. Should this be occurring?
  2. Is this a SwiftUI bug lurking around or is this expected behaviour?
user14305195
  • 719
  • 1
  • 6
  • 11

2 Answers2

1
  1. Yes, your expectation would be correct. However, it looks like a bug.

The problem appear when having content inside NavigationView. If you use .onAppear() on the NavigationView, you will see it called only once. If you use onAppear() on the VStack, it's already twice.

This has reported in this thread aswell

  1. From my view, this behavior is wrong. Maybe report to Apple or ask why
davidev
  • 7,694
  • 5
  • 21
  • 56
  • Thanks for the reply. I can confirm that it is the NavigationView inside the TabView that is causing the problem. If I uncomment the NavigationView, everything works as expected. – user14305195 Dec 18 '20 at 06:30
0

maybe I found a solution: add on every very first NavigationLink the modifier .isDetailLink(false) for me it stops the double onAppear calls