SwiftUI flow coordinator to control navigation in your App.
- iOS 16.0+, iPadOS 16.0+, MacOS 13.0+ (supports Mac Catalyst)
- Swift 5.0+
KVKFlowCoordinators is available through CocoaPods or Swift Package Manager.
pod 'KVKFlowCoordinators'
Adding Pods to an Xcode project
- In Xcode navigate to File → Swift Packages → Add Package Dependency...
- Select a project
- Paste the repository URL (
https://github.com/kvyatkovskys/KVKFlowCoordinators
) and click Next. - For Rules, select Version (Up to Next Major) and click Next.
- Click Finish.
Adding Package Dependencies to Your App
- Import
KVKFlowCoordinators
- Create an entities with type of navigation (for ex.):
enum SheetType: FlowTypeProtocol { case detail var pathID: String { "detail" } }
- Create a coordinator that inherits from the
FlowCoordinator
base class if you want to use:.sheet
.navigationDestination
.fullScreenCover
- Or use a specific coordinator class:
SheetCoordinator
LinkCoordinator
CoverCoordinator
SheetAndLinkCoordinator
SheetAndCoverCoordinator
LinkAndCoverCoordinator
- Create a
CoordinatorView
-> use theFlowCoordinatorView
orFlowCoordinatorSplitView
view with the created coordinator inside bodyvar body: some View { FlowCoordinatorView(coordinator) { // content } } var body: some View { content .flowCoordinator(coordinator) } var body: some View { FlowCoordinatorSplitView(sideBarCoordinator, detailCoordinator) { // side bar content } detail: { // detail content } }
To work with navigation link use
.flowLink(for: NavigationLinkType.self) { (item) in
// content
}
- .navigationDestination(item: $item)
- .flowLink(item: $item)
- Pops all the views on the stack except the root view:
func popToRoot()
- Pops the top view from the navigation stack:
func popView()
- Pops views until the specified view is at the top of the navigation stack. Works only if use
coordinator.linkType
:Thefunc popToView(_ pathID: String) -> [String]
pathID
that you want to be at the top of the stack. This view must currently be on the navigation stack. An array containing the path link IDs that were popped from the stack.
final class ContentCoordinator: FlowCoordinator<SheetType, LinkType, CoverType> {
@Published var vm: ContentViewModel!
private(set) var secondContentCoordinator: SecondContentCoordinator!
init() {
super.init()
vm = ContentViewModel(coordinator: self)
secondContentCoordinator = SecondContentCoordinator(parentCoordinator: self, title: "Second Coordinator")
}
}
struct ContentCoordinatorView: View {
@StateObject private var coordinator = ContentCoordinator()
var body: some View {
ContentView(vm: coordinator.vm)
.fullScreenCover(item: $coordinator.coverType) { (item) in
SheetView(title: "Cover View")
}
.sheet(item: $coordinator.sheetType) { (item) in
switch item {
case .sheetFirst(let title):
SheetView(title: title)
}
}
.flowLink(for: NavigationLinkType.self) { (item) in
switch item {
case .linkFirstWithParams(let title):
NavigationLinkView(title: title)
case .linkSecond:
NavigationLinkView(title: "Test Second Link")
case .linkSecondCoordinator:
SecondContentCoordinatorView(coordinator: coordinator.secondContentCoordinator)
}
}
}
}
final class ContentViewModel: ObservableObject {
private let coordinator: ContentCoordinator
init(coordinator: ContentCoordinator) {
self.coordinator = coordinator
}
func openFirstLink() {
coordinator.linkType = .linkFirstWithParams("First Link View")
}
}
struct ContentView: View {
@ObservedObject var vm: ContentViewModel
var body: some View {
VStack(spacing: 30) {
Button("Open Sheet") {
vm.openSheetFirst(autoClose: false)
}
Button("Open Auto Close Sheet") {
vm.openSheetFirst(autoClose: true)
}
Button("Open Cover") {
vm.openCoverFirst()
}
Button("Open Link First") {
vm.openFirstLink()
}
Button("Open Complex Btn Link") {
vm.openComplexLink()
}
NavigationLink("Open Complex Nav Link",
value: ContentViewModel.LinkType.linkSecondCoordinator)
}
}
}
Screen.Recording.2024-02-17.at.1.49.12.PM.mov
KVKFlowCoordinators is available under the MIT license