Skip to content

Instantly share code, notes, and snippets.

@camcaine
Last active February 25, 2021 08:18
Show Gist options
  • Save camcaine/9d81ea4a1cda123cfaceba70fb39c711 to your computer and use it in GitHub Desktop.
Save camcaine/9d81ea4a1cda123cfaceba70fb39c711 to your computer and use it in GitHub Desktop.
Managing TabView selections in SwiftUI
import SwiftUI
protocol TabSelectable {
associatedtype Tab
func shouldSelect(_ tab: Tab) -> Bool
}
@propertyWrapper
struct TabSelection<Value: Hashable> {
init(wrappedValue: Value) {
_selection = wrappedValue
}
var _selection: Value
private var selectable: ((Value) -> Bool)?
mutating func register<S>(_ selectable: S) where S : TabSelectable, Value == S.Tab {
self.selectable = selectable.shouldSelect
}
var wrappedValue: Value {
get { _selection }
set {
guard selectable?(newValue) ?? true else {
return
}
_selection = newValue
}
}
}
enum TabName: Hashable {
case home
case news
case more
}
class TabSelect: ObservableObject, TabSelectable {
init() {
_selection.register(self)
}
func shouldSelect(_ tab: TabName) -> Bool {
guard tab != .more else {
showModal.toggle()
return false
}
return true
}
@TabSelection var selection = Tab.home {
willSet {
objectWillChange.send()
}
}
var showModal = false
}
struct ContentView: View {
@StateObject var tabSelect = TabSelect()
var body: some View {
TabView(selection: $tabSelect.selection) {
Text("Home")
.tabItem {
Text("Home")
}
.tag(TabName.home)
Text("News")
.tabItem {
Text("News")
}
.tag(TabName.news)
Text("More")
.tabItem {
Text("More")
}
.tag(TabName.more)
}
.sheet(isPresented: $tabSelect.showModal) {
Text("Modal")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment