Skip to content

Commit 24cfc5c

Browse files
authored
Merge pull request #37 from mattevigo/feature/injection
Add initializer that takes a NavigationStack as parameter
2 parents 6c73e79 + 3f1cbc6 commit 24cfc5c

File tree

2 files changed

+60
-7
lines changed

2 files changed

+60
-7
lines changed

README.md

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,47 @@ struct ChildView: View {
278278
}
279279
```
280280

281+
## NavigationStack injection
282+
283+
By default you can programmatically push and pop only inside the `NavigationStackView` hierarchy (by accessing the `NavigationStack` environment object). If you want to use the `NavigationStack` outside the `NavigationStackView` you need to create your own `NavigationStack` (wherever you want) **and pass it as parameter to the `NavigationStackView`**.
284+
285+
**Important:** Every `NavigationStack` must be associated to a `NavigationStackView`. A `NavigationStack` cannot be shared between multiple `NavigationStackView`.
286+
287+
This is useful when you want to _decouple your routing logic from views by using your own router class_, for example:
288+
289+
```
290+
class MyRouter {
291+
private let navStack: NavigationStack
292+
293+
init(navStack: NavigationStack) {
294+
self.navStack = navStack
295+
}
296+
297+
func rootView() -> some View {
298+
RootView()
299+
}
300+
301+
func toLogin() {
302+
self.navStack.push(LoginScreen())
303+
}
304+
305+
func toSignUp() {
306+
self.navStack.push(SignUpScreen())
307+
}
308+
}
309+
310+
struct RootView: View {
311+
let navStack: NavigationStack
312+
let router: MyRouter
313+
314+
var body: some View {
315+
NavigationStackView(navigationStack: navStack) {
316+
router.rootView()
317+
}
318+
}
319+
}
320+
```
321+
281322
## Important
282323

283324
Please, note that `NavigationStackView` navigates between views and two views may be smaller than the entire screen. In that case the transition animation won't involve the whole screen, but just the two views. Let's make an example:
@@ -411,5 +452,3 @@ struct MyView: View {
411452

412453
SwiftUI is really new, there are some bugs in the framework (or unexpected behaviours) and several API not yet documented. Please, report any issue may arise and feel free to suggest any improvement or changing to this first implementation of a navigation stack.
413454

414-
415-

Sources/NavigationStack/NavigationStack.swift

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,19 @@ public enum PopDestination {
4545
// MARK: ViewModel
4646

4747
public class NavigationStack: ObservableObject {
48+
49+
/// Default transition animation
50+
public static let defaultEasing = Animation.easeOut(duration: 0.2)
51+
4852
fileprivate private(set) var navigationType = NavigationType.push
53+
4954
/// Customizable easing to apply in pop and push transitions
5055
private let easing: Animation
51-
52-
init(easing: Animation) {
56+
57+
public init(easing: Animation = defaultEasing) {
5358
self.easing = easing
5459
}
55-
60+
5661
private var viewStack = ViewStack() {
5762
didSet {
5863
currentView = viewStack.peek()
@@ -153,9 +158,18 @@ public struct NavigationStackView<Root>: View where Root: View {
153158
/// - transitionType: The type of transition to apply between views in every push and pop operation.
154159
/// - easing: The easing function to apply to every push and pop operation.
155160
/// - rootView: The very first view in the NavigationStack.
156-
public init(transitionType: NavigationTransition = .default, easing: Animation = .easeOut(duration: 0.2), @ViewBuilder rootView: () -> Root) {
161+
public init(transitionType: NavigationTransition = .default, easing: Animation = NavigationStack.defaultEasing, @ViewBuilder rootView: () -> Root) {
162+
self.init(transitionType: transitionType, navigationStack: NavigationStack(easing: easing), rootView: rootView)
163+
}
164+
165+
/// Creates a NavigationStackView with the provided NavigationStack
166+
/// - Parameters:
167+
/// - transitionType: The type of transition to apply between views in every push and pop operation.
168+
/// - navigationStack: the shared NavigationStack
169+
/// - rootView: The very first view in the NavigationStack.
170+
public init(transitionType: NavigationTransition = .default, navigationStack: NavigationStack, @ViewBuilder rootView: () -> Root) {
157171
self.rootView = rootView()
158-
self.navViewModel = NavigationStack(easing: easing)
172+
self.navViewModel = navigationStack
159173
switch transitionType {
160174
case .none:
161175
self.transitions = (.identity, .identity)

0 commit comments

Comments
 (0)