{"id":20684086,"url":"https://github.com/silkodenis/swiftui-navigation-coordinator","last_synced_at":"2026-04-24T13:06:40.446Z","repository":{"id":237004275,"uuid":"793612171","full_name":"silkodenis/swiftui-navigation-coordinator","owner":"silkodenis","description":"A lightweight SwiftUI Navigation Coordinator package that supports stack navigation and modal presentation.","archived":false,"fork":false,"pushed_at":"2024-09-08T08:55:25.000Z","size":1702,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-10T21:53:59.261Z","etag":null,"topics":["coordinator","dismiss","example","ios","modal","navigation","pattern","pop","present","push","segue","stack","unwind","unwind-segue","xcodeproj"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/silkodenis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-29T14:49:10.000Z","updated_at":"2024-10-15T20:24:18.000Z","dependencies_parsed_at":"2024-09-07T18:52:20.771Z","dependency_job_id":"dbdd41ee-e4fe-4af5-930b-887e9623709b","html_url":"https://github.com/silkodenis/swiftui-navigation-coordinator","commit_stats":null,"previous_names":["silkodenis/swiftui-navigation-coordinator"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/silkodenis/swiftui-navigation-coordinator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silkodenis%2Fswiftui-navigation-coordinator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silkodenis%2Fswiftui-navigation-coordinator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silkodenis%2Fswiftui-navigation-coordinator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silkodenis%2Fswiftui-navigation-coordinator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/silkodenis","download_url":"https://codeload.github.com/silkodenis/swiftui-navigation-coordinator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silkodenis%2Fswiftui-navigation-coordinator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32224425,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-24T10:26:35.452Z","status":"ssl_error","status_checked_at":"2026-04-24T10:25:27.643Z","response_time":64,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coordinator","dismiss","example","ios","modal","navigation","pattern","pop","present","push","segue","stack","unwind","unwind-segue","xcodeproj"],"created_at":"2024-11-16T22:19:03.393Z","updated_at":"2026-04-24T13:06:40.380Z","avatar_url":"https://github.com/silkodenis.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![License](https://img.shields.io/github/license/silkodenis/swiftui-navigation-coordinator.svg)](https://github.com/silkodenis/swiftui-navigation-coordinator/blob/main/LICENSE)\n![swift](https://github.com/silkodenis/swiftui-navigation-coordinator/actions/workflows/swift.yml/badge.svg?branch=main)\n\n# SwiftUI Navigation Coordinator\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/silkodenis/swiftui-navigation-coordinator/blob/readme_assets/screenshots/orange.png?raw=true\" alt=\"Screenshot 1\" width=\"200\"/\u003e\n  \u003cimg src=\"https://github.com/silkodenis/swiftui-navigation-coordinator/blob/readme_assets/screenshots/red.png?raw=true\" alt=\"Screenshot 2\" width=\"200\"/\u003e\n  \u003cimg src=\"https://github.com/silkodenis/swiftui-navigation-coordinator/blob/readme_assets/screenshots/green.png?raw=true\" alt=\"Screenshot 3\" width=\"200\"/\u003e\n  \u003cimg src=\"https://github.com/silkodenis/swiftui-navigation-coordinator/blob/readme_assets/screenshots/blue.png?raw=true\" alt=\"Screenshot 4\" width=\"200\"/\u003e\n\u003c/p\u003e\n\n## About the Project\nThis project provides a lightweight Navigation Coordinator, using SwiftUI NavigationStack (available from iOS 16).\n\n## Core Features\nThe current implementation covers 6 main transitions:\n\n\u003cdetails open\u003e\n\u003csummary\u003eStack Navigation:\u003c/summary\u003e\n\n- `push` — navigates forward to a new view.\n- `pop` — returns to the previous view.\n- `unwind` — performs a multi-level return.\n- `popToRoot` — returns to the root view.\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n\u003csummary\u003eModal Presentation:\u003c/summary\u003e\n\n- `present` — displays a modal view, overlaying it on top of current content.\n- `dismiss` — closes the current modal view and returns to the underlying content.\n\n\u003c/details\u003e\n\n## Requirements\n\n- **iOS**: iOS 16.0+\n- **macOS**: macOS 13.0+\n- **watchOS**: watchOS 9.0+\n- **tvOS**: tvOS 16.0+\n\n## Add with Swift Package Manager:\n\n1. Open Xcode and select “File” \u003e “Add Packages…”\n2. Enter the URL of the package repository.\n3. Follow the instructions to complete the installation.\n\n## Getting Started\n\n\u003cdetails open\u003e\n\u003csummary\u003e\u003cb\u003e1. Configure the NavigableScreen Enum\u003c/b\u003e\u003c/summary\u003e\n  \nStart by creating an enum Screen to represent the different screens in your app. Ensure it conforms to the NavigableScreen protocol:\n\n```swift\nimport NavigationCoordinator\n\nenum Screen {\n    case login\n    case movies\n    case settings\n    // etc.\n}\n\nextension Screen: NavigableScreen {\n    @ViewBuilder\n    var view: some View {\n        switch self {\n        case .login: LoginView()\n        case .movies: MoviesView()\n        case .settings: SettingsView()\n        }\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n\u003csummary\u003e\u003cb\u003e2. Define Typealiases\u003c/b\u003e\u003c/summary\u003e\n  \nDefine typealias to simplify the usage of the types used with your coordinator:\n\n```swift\nimport NavigationCoordinator\n\ntypealias SegueModifier = RegisterSegueModifier\u003cScreen\u003e\ntypealias Coordinator = NavigationCoordinator\u003cScreen\u003e\ntypealias RootView = NavigationStackRootView\u003cScreen\u003e\n```\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n\u003csummary\u003e\u003cb\u003e3. Configure the App Entry Point\u003c/b\u003e\u003c/summary\u003e\n  \nSet up the app entry point using the RootView to define the initial screen:\n\n```swift\nimport SwiftUI\n\n@main\nstruct MainApp: App {\n    var body: some Scene {\n        WindowGroup {\n            RootView(.login)\n        }\n    }\n}\n```\n\u003c/details\u003e\n\n## Usage Examples\n\n\u003cdetails open\u003e\n\u003csummary\u003e\u003cb\u003ePush\u003c/b\u003e\u003c/summary\u003e\n\n```swift\nimport SwiftUI\n\nstruct LoginView: View {\n    @EnvironmentObject var coordinator: Coordinator\n    \n    var body: some View {\n        Button(\"Movies\") {\n            coordinator.push(.movies)\n        }\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003ePop\u003c/b\u003e\u003c/summary\u003e\n\n```swift\nimport SwiftUI\n\nstruct MoviesView: View {\n    @EnvironmentObject var coordinator: Coordinator\n    \n    var body: some View {\n        Button(\"back\") {\n            coordinator.pop()\n        }\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003ePopToRoot\u003c/b\u003e\u003c/summary\u003e\n\n```swift\nimport SwiftUI\n\nstruct SettingsView: View {\n    @EnvironmentObject var coordinator: Coordinator\n    \n    var body: some View {\n        Button(\"login\") {\n            coordinator.popToRoot()\n        }\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eUnwind\u003c/b\u003e\u003c/summary\u003e\nUse a unique identifier for your unwind segues. If a segue becomes no longer relevant, it will be automatically removed from the coordinator. Using `onUnwind()` modifier is completely safe, tested, and does not involve any memory leaks or unintended calls. \n\n\n\n```swift\nimport SwiftUI\n\n// B View\n// 🟦🟦🅰🟦🟦🟦🟦🟦🟦🅱️  \nstruct B: View {\n    @EnvironmentObject var coordinator: Coordinator\n    \n    var body: some View {\n        Button(\"pop to A\") {\n            coordinator.unwind(to: \"identifier\" /*, with: Any?*/)\n        }\n    }\n}\n\n// A View\n// 🟦🟦🅰️\nstruct A: View {\n    var body: some View {\n        VStack {}\n            .onUnwind(segue: \"identifier\") /*{ Any? in }*/\n    }\n}\n```\n`onUnwind()` will always be called before `onAppear()`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003ePresent\u003c/b\u003e\u003c/summary\u003e\n\n```swift\nimport SwiftUI\n\n/*\n               [B]\n[ ][ ][ ][ ][ ][A]\n*/\nstruct A: View {\n    @EnvironmentObject var coordinator: Coordinator\n    \n    var body: some View {\n        Button(\"present\") {\n            coordinator.present(.B)\n        }\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eDismiss\u003c/b\u003e\u003c/summary\u003e\n\n```swift\nimport SwiftUI\n\n/*\n               [B][ ][ ][ ][CL]\n[ ][ ][ ][ ][ ][A]\n*/\nstruct CL: View {\n    @EnvironmentObject var coordinator: Coordinator\n    \n    var body: some View {\n        Button(\"dismiss\") {\n            coordinator.dismiss(/*to: \"identifier\" /*, with: Any?*/*/)\n        }\n    }\n}\n\n/*\n[ ][ ][ ][ ][ ][A]\n*/\nstruct A: View {\n    @EnvironmentObject var coordinator: Coordinator\n    \n    var body: some View {\n        VStack {}\n            // Not necessary. Only if you need to capture an onDismiss event.\n            .onDismiss(segue: \"identifier\") /*{ Any? in }*/\n    }\n}\n\n```\n\u003c/details\u003e\n\n## Project examples\n- [Original Example](https://github.com/silkodenis/swiftui-navigation-coordinator/tree/main/Example)\n- [SwiftUI Redux TMDB Demo App](https://github.com/silkodenis/swiftui-moviesdb-redux-app)\n\n## Reporting Issues\n\nI welcome any issues you find within the project. If you encounter bugs or have suggestions for improvements, please feel free to create an issue on the GitHub repository.\n\n\n## License\n\n**Apache License 2.0**. See the [LICENSE](https://github.com/silkodenis/swiftui-navigation-coordinator/blob/main/LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsilkodenis%2Fswiftui-navigation-coordinator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsilkodenis%2Fswiftui-navigation-coordinator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsilkodenis%2Fswiftui-navigation-coordinator/lists"}