{"id":26742455,"url":"https://github.com/lab49/swiftui-multi-nav","last_synced_at":"2025-03-28T06:18:13.756Z","repository":{"id":267493917,"uuid":"901412126","full_name":"lab49/swiftui-multi-nav","owner":"lab49","description":"SwiftUI navigation made easy","archived":false,"fork":false,"pushed_at":"2024-12-10T16:31:56.000Z","size":100,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2024-12-10T17:47:17.826Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lab49.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-12-10T15:58:19.000Z","updated_at":"2024-12-10T16:32:00.000Z","dependencies_parsed_at":"2024-12-10T17:47:19.945Z","dependency_job_id":"a930f48a-6fe8-4ab5-b372-1879a0e3ffbd","html_url":"https://github.com/lab49/swiftui-multi-nav","commit_stats":null,"previous_names":["lab49/swiftui-multi-nav"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lab49%2Fswiftui-multi-nav","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lab49%2Fswiftui-multi-nav/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lab49%2Fswiftui-multi-nav/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lab49%2Fswiftui-multi-nav/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lab49","download_url":"https://codeload.github.com/lab49/swiftui-multi-nav/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245978283,"owners_count":20703678,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2025-03-28T06:18:13.184Z","updated_at":"2025-03-28T06:18:13.750Z","avatar_url":"https://github.com/lab49.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MultiNav\nA SwiftUI navigation scheme (iOS 17 only), providing an easy-to-use interface for presenting Views, and managing ViewModels.\n\n## Features\n\n- The Navigation stack is managed using **push()**, **pop()**, **popToRoot()**, and **jumpTo()**, from either the View, or ViewModel. \n- All Views belonging to a given Navigation stack are defined in one central location (**NavigationScreenDefinition** enum).\n- Simplified, standardized modal presentation.\n- All ViewModels are owned, and their lifetimes managed, by a central **NavigationCoordinator** (and not by other Views, or ViewModels).\n- A single instance of a ViewModel can be shared between multiple Views.\n\n## Limitations\n\n- The **NavigationCoordinator** supports no more than one ViewModel per View.\n- Each View/ViewModel combo must be uniquely identifiable by one or more **Hashable** elements.\n\n## Modals\n\nA parent View can easily present a child View as a sheet, or a fullScreenCover.  Alerts can be easily presented, and managed as well.  In order to do this:\n\n 1. The parent ViewModel must inherit from **ModalPresenter**.\n 2. The parent View must use the **.modalPresenting()** view modifier.\n 3. The presented (child) View must be defined in the same **NavigationScreenDefinition** enum as its parent View.\n 4. **ModalPresenter.presentModal()**, and **ModalPresenter.presentAlert()** can be used from either the View, or the ViewModel.\n\n## Technical Notes\n\n### NavigationRootView\nRepresents the root of a navigation stack.  An app can contain one or more of these.  Each one requires its own instance of **NavigationCoordinator**, which in turn requires a **NavigationScreenDefinition** enum.\n\n### NavigationScreenDefinition\nProtocol. Typically implemented by an enum, with associated values. Each instance (enum case) corresponds to a screen in the app.\n\n### NavigationScreenDefinition.screenView()\nThis func must be implemented to return the actual View corresponding to each **NavigationScreenDefinition** instance.  This may also involve creating a corresponding ViewModel.\n\n### NavigationCoordinator\nThe relevant instance of this is automatically available (via Environment) to every View under a given navigation stack (**NavigationRootView**).  It can also be provided to any ViewModel, upon creation.\n\n### NavigationCoordinator.push(), pop(), popToRoot()\nCan be called from View, or ViewModel, as needed.\n\n### NavigationCoordinator.jumpTo()\nReplaces the entire navigation stack with another one, in a single call.\n\n### NavigationCoordinator.observable(for: default:)\nCall this func to create and register a ViewModel, or simply return it, if it already exists.  *(ViewModels are automatically released when their corresponding Views are dismissed).*  Typically used within **NavigationScreenDefinition.screenView()**, during View creation.\n\n### ModalPresentor\nMake this the superclass of a ViewModel in order to facilitate modal presentation of Views from either it, or its corresponding View.  This also facilitates flexible presentation and handling of alerts.\n- The corresponding View must apply the **.modalPresenting()** view modifier (wherever the .sheet(), or .fullScreenCover() modifiers would be used).\n- A single **ModalPresentor** ViewModel cannot be shared across more than one View needing to present child Views modally.\n\n### ModalPresentor.presentModal(_: isFullScreen:)\nCan be called from View, or ViewModel, as needed.\n\n### ModalPresentor.presentAlert()\nCan be called from View, or ViewModel, as needed.\n\n### ModalPresentor.handleAlertButton(id:)\nOverride this func in a ViewModel.  It is called whenever an alert button is tapped.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flab49%2Fswiftui-multi-nav","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flab49%2Fswiftui-multi-nav","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flab49%2Fswiftui-multi-nav/lists"}