Skip to content

mercen-lee/FlowKit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FlowKit

Swift Platforms Swift Package Manager License

SwiftUI is great. But navigation isn't.

FlowKit is a lightweight UIKit-backed navigation helper for SwiftUI.

Requirements

Platform Minimum Swift Version Installation
iOS 13.0+ 5.5 Swift Package Manager

Installation

Swift Package Manager

  • File -> Add Packages... And paste the repository URL.
  • Or add it to the dependencies value of your Package.swift.
dependencies: [
  .package(url: "https://github.com/Mercen-Lee/FlowKit.git", .branch("main"))
]

Usage

  • Push View
flow.push(NextView())
// or
flow.push(NextView(), animated: false)
// Preserve a tab bar when pushing inside tab-based apps.
flow.push(NextView(), preserveTabBar: true)
flow.tabPush(NextView())
  • Pop View
flow.pop()
flow.pop(3) // Removes up to 3 views, clamped at the root view.
  • Pop View to Root
flow.popToRoot()
  • Replace Views
flow.replace([StepView(index: 1), StepView(index: 2)])
// Heterogeneous view types can use the builder, variadic overloads, or AnyView.
flow.replace {
  FirstView()
  SecondView()
}
flow.replace(FirstView(), SecondView())
flow.replace([AnyView(FirstView()), AnyView(SecondView())])
  • Switch Views
flow.switchToView(at: 0)
flow.moveView(from: 0, to: 2)
flow.moveTopView(to: 0)
  • Reload View
flow.reload()
  • Navigation Bar
FlowPresenter(rootView: ContentView(), navigationBarHidden: true)
flow.hideNavigationBar()
flow.showNavigationBar()
  • Present Sheet
flow.sheet(SheetView())
flow.fullScreenCover(FullScreenView())
  • Present Alert
let alert = Alert(title: "Error",
                  message: "Not Found",
                  dismissButton: .default("Ok"))
flow.alert(alert)
  • Deep Link
flow.registerDeepLink(.init(path: "/details") { url, flow in
  flow.push(DetailView())
})

flow.openDeepLink(URL(string: "myapp://host/details")!)

Example

App

import SwiftUI
import FlowKit

@main
struct SampleApp: App {
  var body: some Scene {
    WindowGroup {
      FlowPresenter(rootView: ContentView())
    }
  }
}

View

struct ContentView: View {
  @Flow var flow
  var body: some View {
    Button {
      flow.push(NextView())
    } label: {
      Text("Push")
    }
  }
}

struct NextView: View {
  @Flow var flow
  var body: some View {
    Button {
      flow.pop()
    } label: {
      Text("Pop")
    }
  }
}

FlowPresenter injects FlowProvider through a weak environment value, so pushed SwiftUI views can use @Flow without retaining the provider as an EnvironmentObject.

FlowPresenter keeps the backing provider alive with SwiftUI state, which avoids resetting the navigation controller when the presenter view is rebuilt. Navigation commands target the active navigation controller, including the selected tab when FlowKit is embedded in a tab bar. Sheets, full-screen covers, and alerts are presented from the top-most visible view controller.

Development

FlowKit depends on UIKit, so build it for an iOS destination instead of running a plain macOS swift test.

xcodebuild -scheme FlowKit -destination 'generic/platform=iOS' CODE_SIGNING_ALLOWED=NO build

TCA Example

Dependency

struct FlowDependency: DependencyKey {
  static var liveValue: FlowProvider {
    FlowProvider(rootView: ContentView())
  }
}

extension DependencyValues {
  var flow: FlowProvider {
    get { self[FlowDependency.self] }
    set { self[FlowDependency.self] = newValue }
  }
}

Reducer

struct Content: Reducer {
  @Dependency(\.flow) var flow
  ...
}

Releases

No releases published

Packages

 
 
 

Contributors

Languages