Skip to content

Repository files navigation

Platform-iOSPlatform-macOSLicense: MIT

NavigationStackEX

Abstract encapsulation of the default NavigationStack with custom functionalities aimed at simplifying SwiftUI view management and navigation.

Push, present, and pop your views elegantly, helping you reduce time, complexity, and maintain code clarity.

And it's Super Lightweight!

screenshotscreenshot

Features

✅ 100% SwiftUI

✅ Powerful solution for your Navigation

✅ Super easy-to-use

✅ Lightweight

✅ Supports any kind of Views

✅ Can dynamically push / present your Views in a SwiftUI

✅ Can predefine the pre-loading of your views in the app, ahead of use, in a more conventional way if needed

⚠️ Known limitation: The display of modal views (for 'present' and 'presentFullScreen') are not stackable as of right now (will be in the future)

Requirements

  • iOS 16.0+, macOS 14.0+
  • SwiftUI 5.0+

Installation

Swift Package Manager:

XCode > File > Add Package Dependency...

Enter the following URL of the repository into the search:

https://github.com/MaximeFILIPPI/NavigationStackEX

Follow the prompts to complete the installation.


Setup

Here is an example of how to integrate and use NavigationStackEX in your SwiftUI project:

import SwiftUI
import NavigationStackEX // <- Import
@mainstructYourProject:App{varbody:someScene{WindowGroup{NavigationStackEX{ // <- use THIS instead of NavigationStack
ContentView()}}}}

Basic Usage

To navigate between your views, simply add @EnvironmentObject var navigator: Navigator Then use the navigator functions as push, present, presentFullScreen, pop, popToRoot, dismiss to trigger the navigation:

import SwiftUI
import NavigationStackEX // <- Import
structContentView:View{@EnvironmentObjectvarnavigator:Navigator // <- Add this line to the view
varbody:someView{VStack{Button("Go to Profile"){self.goToNextScreen()}}}func goToNextScreen(){
navigator.push(to:ProfileView()) // <- use THIS to navigate
}}

THAT'S IT!


Detailed Navigation Usage

PUSH

Navigate to next screen

// Navigate to a SwiftUI view instance
navigator.push(to:ProfileView())

POP

Back to previous screen

// Back to the previous SwiftUI view
navigator.pop()

Back to the root of your navigation

// Back to the very first SwiftUI view
navigator.popToRoot()

Back to a specific screen in the stack

Note: You must use the parameter "identifier" when navigating to activate this functionnality (example: navigator.push(to: ProfileView(), identifier: "profile")))

// Back to a specified SwiftUI view
navigator.pop(to:"profile") // <- will take you back to the profile view in your navigation stack

PRESENT

Note: Be careful the present modal way of displaying views is not stackable at the moment.

// Navigate to a SwiftUI view instance
navigator.present(ProfileView())

PRESENT FULL SCREEN

Cover opening full screen

// Navigate to a SwiftUI view instance
navigator.presentFullScreen(ProfileView())

DISMISS

Close a modal that has been present or presentFullScreen:

// Navigate to a destination navigator.dismiss()

Passing Data

How to pass data? Just like any SwiftUI views:

// Set data using a view instance
navigator.push(to:ProfileView(name:"Max"))

Customization

BACK BUTTON

You can change the back button of the navigation bar if you wish:

import SwiftUI
import NavigationStackEX
structTempScreenView:View{varbody:someView{ZStack{Color.red
}.navigationBackButtonItem(Text("Back")) // Customize back button if needed (can be any view)
}}

RIGHT ITEM / LEFT ITEM

or the left / right navigation bar items :

import SwiftUI
import NavigationStackEX
structTempScreenView:View{varbody:someView{ZStack{Color.red
}.navigationLeftViewItem(YourOwnCustomBackButtonView()) // <- Right navigation bar button (your own custom view)
.navigationRightViewItem(YourOwnCustomLogoView()) // <- Left navigation bar button (your own custom view)
}}

LARGE TITLE

Change the way the title is diplayed (Large or Inline)

import SwiftUI
import NavigationStackEX
structTempScreenView:View{varbody:someView{ZStack{Color.red
}.navigationTitle("Title").navigationBarHidden(false).toolbarTitleDisplayMode(.large) // Large or Inline for better user experience (avoid using automatic)
}}

HIDDEN TITLE

or not displayed at all and hide the navigation bar:

import SwiftUI
import NavigationStackEX
structTempScreenView:View{varbody:someView{ZStack{Color.red
}.navigationBarTitle("").navigationBarHidden(true)}}

(OPTIONAL) TRADITIONAL NAV STYLE

For people that prefers to keep everything tidy in one class only, you can use a more traditional approach to navigate by declaring and pre-loading the screens (SwiftUI views) that you need before using them.

import SwiftUI
import NavigationStackEX // <- Import
@mainstructYourProject:App{@Statevarsegues:[String:AnyView]=[:] // <- Add this line to prepare destinations
varbody:someScene{WindowGroup{NavigationStackEX(destinations: $segues){ // <- The NavigationEX
ContentView() // <- Your root view (first view)
}.onAppear{self.setupNavigation()}}}
// You can setup the destinations ahead of time // By predefining your views with associated tags
// It allows you to navigate in a more classical way by referencing tags instead of views instance
func setupNavigation(){
// Example for a profile view in your app
self.segues["profile"]=ProfileView().any // <- add .any modifier behind your view
// Add more segues as needed
}}

Then use the functions like this:

PUSH

// Navigate to a destination from a tag
navigator.push(to:"profile")

POP

// Back to the previous SwiftUI view
navigator.pop()
// Back to the very first SwiftUI view
navigator.popToRoot()
// Back to a specified SwiftUI view
navigator.pop(to:"profile") // <- will take you back to the profile view of your app, wherever it is in your navigation stack

PRESENT

// Navigate to a destination navigator.present("profile")

PRESENT FULL SCREEN

// Navigate to a destination navigator.presentFullScreen("profile")

DISMISS

Close a modal that has been present or presentFullScreen:

// Navigate to a destination navigator.dismiss()

PASSING / RETRIEVING DATA

How to pass data:

// Set data using a destination (tag reference)
letdata:String="Max" // <- Can be any type of data, primivite, objects, etc...
navigator.push(to:"profile", with: data)

Get the data:

navigator.data(for:"profile")as?String // <- Can be any type of data, primivite, objects, etc...

Profile class example when retrieving data:

structProfileView:View{@Statevarname:String=""varbody:someView{ZStack{Text(name)}.onAppear{loadInfos()}}func loadInfos(){iflet profileData = navigator.data(for:"profile")as?String // <- Get it here
{
name = profileData
}}}

License

SnapPager is available under the MIT license. See the LICENSE file for more details.


Credits

NavigationStackEX is developed and maintained by [Maxime FILIPPI].

If you encounter any issues or have suggestions for improvements, please open an issue.

About

Elegant solution for navigation management in SwiftUI. Super simple, powerful, easy-to-use & customizable (for SwiftUI 5+ / iOS 16+).

Topics

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages