From f9aa409a9254591806ba050b9fd8c26b2c0c432a Mon Sep 17 00:00:00 2001 From: Nicholas Bellucci Date: Tue, 12 May 2020 12:29:00 -0400 Subject: [PATCH] Removed need to pass selected index when initializing, readme updates --- Example/Example/ContentView.swift | 3 +- README.md | 28 +++++++++++++++-- Sources/StatefulTabView/StatefulTabView.swift | 30 ++++++++++++++----- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/Example/Example/ContentView.swift b/Example/Example/ContentView.swift index 8d4b9bb..52774c9 100644 --- a/Example/Example/ContentView.swift +++ b/Example/Example/ContentView.swift @@ -9,11 +9,10 @@ import SwiftUI struct ContentView: View { - @State var selectedIndex: Int = 0 @State var badgeValue1: String? = "1" var body: some View { - StatefulTabView(selectedIndex: $selectedIndex) { + StatefulTabView { Tab(title: "Tab 1", systemImageName: "circle.fill", badgeValue: $badgeValue1) { NavigationView { List { diff --git a/README.md b/README.md index 67e5b89..013c191 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ In Xcode 11 or greater, navigate to `File > Swift Packages > Add Package Depende - [x] TabBarItem custom title and image - [x] TabBarItem badge value - [x] State retention from tab to tab -- [x] Pop to root functionality when clicking selected index +- [x] Pop to root functionality when selecting the already selected tab ## Usage @@ -32,7 +32,7 @@ Setting up StatefulTabView is relatively simple and works similar to the native ### Basic ```Swift -StatefulTabView(selectedIndex: $selectedIndex) { +StatefulTabView { Tab(title: "Tab 1", systemImageName: "circle.fill") { NavigationView { List { @@ -55,7 +55,7 @@ StatefulTabView(selectedIndex: $selectedIndex) { All appearance modifications can be made by using extensions for the StatefulTabView. ```Swift -StatefulTabView(selectedIndex: $selectedIndex) { +StatefulTabView { ... } .barTintColor(.red) @@ -63,6 +63,16 @@ StatefulTabView(selectedIndex: $selectedIndex) { .barAppearanceConfiguration(.transparent) ``` +### Selected Index + +The selected index of the StatefulTabView can be set within the initializer. The passed value is a binding. + +```Swift +StatefulTabView(selectedIndex: $selectedIndex) { + ... +} +``` + ### BadgeValue The TabBarItem badge value can be set in the initializer of a Tab. The passed value is a binding. @@ -73,6 +83,18 @@ Tab(title: "Tab 1", systemImageName: "circle.fill", badgeValue: $badgeValue) { } ``` +### Single Tab + +Due to the limitations of the current `@_functionBuilder` implementation in Swift, to build a StatefulTabView with one tab `BuilderType.individual` should be passed within the initializer. + +```Swift +StatefulTabView(.individual) { + Tab(title: "Tab 1", systemImageName: "circle.fill") { + ... + } +} +``` + ## License StatefulTabView is, and always will be, MIT licensed. See [LICENSE](LICENSE) for details. diff --git a/Sources/StatefulTabView/StatefulTabView.swift b/Sources/StatefulTabView/StatefulTabView.swift index 42a7095..b093eb9 100644 --- a/Sources/StatefulTabView/StatefulTabView.swift +++ b/Sources/StatefulTabView/StatefulTabView.swift @@ -19,28 +19,44 @@ public struct StatefulTabView: View { internal var backgroundColor: UIColor? = nil internal var tabBarConfiguration: TabBarBackgroundConfiguration? = nil - @Binding internal var selectedIndex: Int + @State private var stateIndex: Int = 0 + @Binding private var bindableIndex: Int - public init(selectedIndex: Binding, _ type: BuilderType, _ content: () -> Tab) { - _selectedIndex = selectedIndex + private var useBindableIndex: Bool = false + + public init(selectedIndex: Binding? = nil, _ type: BuilderType, _ content: () -> Tab) { + if let selectedIndex = selectedIndex { + _bindableIndex = selectedIndex + useBindableIndex = true + } else { + _bindableIndex = .constant(0) + useBindableIndex = false + } let tabController = UIHostingController(rootView: content().view) tabController.tabBarItem = content().barItem viewControllers.append(tabController) } - public init(selectedIndex: Binding, @TabBuilder _ content: () -> [Tab]) { - _selectedIndex = selectedIndex + public init(selectedIndex: Binding? = nil, @TabBuilder _ content: () -> [Tab]) { + if let selectedIndex = selectedIndex { + _bindableIndex = selectedIndex + useBindableIndex = true + } else { + _bindableIndex = .constant(0) + useBindableIndex = false + } + configureViewControllers(with: content()) } - + public var body: some View { TabBarController(controllers: viewControllers, tabBarItems: tabBarItems, barTintColor: barTintColor, backgroundColor: backgroundColor, tabBarConfiguration: tabBarConfiguration, - selectedIndex: $selectedIndex) + selectedIndex: useBindableIndex ? $bindableIndex : $stateIndex) .edgesIgnoringSafeArea(.all) } }