siteline / swiftui-introspect

Introspect underlying UIKit/AppKit components from SwiftUI
MIT License
5.67k stars 351 forks source link

TabView Badge Value get re-initialized #27

Closed agiguere closed 3 years ago

agiguere commented 4 years ago

First off, amazing initiative, really love this for gapping the miss between SwiftUI and UIKit

    TabView { 
     ...
     }
    .introspectTabBarController { tabBarController in
        tabBarController.viewControllers?.first?.tabBarItem.badgeValue = "5" // Test
    }

I used the introspectTabBarController on TabView to set a badgeValue, it works perfectly but as soon as I switch tab, the batch disappears

thanks

ldiqual commented 4 years ago

I'm able to reproduce locally, but I have no idea what is causing this issue. The view controller address remains the same, and the badge value stays the same across updates. Not too sure what is happening to be honest...

agiguere commented 4 years ago

ok no problem, I hope this will be fix in SwiftUI 2 ... do you want me to close this issue?

dscoppelletti commented 3 years ago

Same problem, and I can't guess where I can set the badge again.

SplittyDev commented 3 years ago

@agiguere, @dscoppelletti this is not an Introspect bug.

However, we have found a "hacky" solution to work around this. Take a look at the following code:

struct Issue27: View {
    @State private var tabBarController: UITabBarController?
    @State private var selection: String = ""

    var body: some View {
        TabView(selection: $selection) {
            Text("Foo")
                .tabItem { Text("Foo") }
                .tag("foo")
            Text("Bar")
                .tabItem { Text("Bar") }
                .tag("bar")
        }
        // Listen for change of selection
        .onChange(of: selection, perform: { _ in
            tabBarController?.viewControllers?.first?.tabBarItem.badgeValue = "5"
        })
        .introspectTabBarController { tabBarController in
            self.tabBarController = tabBarController
            tabBarController.viewControllers?.first?.tabBarItem.badgeValue = "5"
        }
    }
}

By saving the UITabBarController somewhere and listening for the selection-change, you can just reset the tabBarItem as soon as another tab is selected.

This is happening because SwiftUI reinitializes the UITabBarItem for some reason. See the following log:

Optional(<UITabBarItem: 0x15c9046c0> title='Foo')
Optional(<UITabBarItem: 0x15c805790> title='Foo' selected)
Optional(<UITabBarItem: 0x15a604b50> title='Foo')
Optional(<UITabBarItem: 0x15a604320> title='Foo' selected)

We'll close this issue, since it's not actually a bug related to Introspect.