GithubHelp home page GithubHelp logo

supervisor194 / navtest Goto Github PK

View Code? Open in Web Editor NEW
1.0 1.0 0.0 30 KB

SwiftUI example of programmatic navigable views for NavigationView hierarchies

License: MIT License

Swift 100.00%
swift swiftui navigationlink navigationview programmatic

navtest's Introduction

NavTest

SwiftUI example of programmatic navigable views for NavigationView hierarchies

This example takes 3 View structs, A,B and C that want to live in a stack navigation view hierarchy. Sometimes we may want to pop the initial view open to the 3rd View C, while maintaining the nice navigation that the stack navigation view provides, the back buttons and forward navigation. The following code has A,B and C conform to a few protocols and adds them to a containing model called the class NavModel: ObservableObject. Additonally, the A,B and C are 'wrapped' by 3 separate View structs to maintain some additional state about what has appeared or disappeared. While not strictly needed to get programmatic navigation working, these wrappers can be helpful in more complex situations where one does not want to instantiate the underlying A,B and C multiple times. One can remove the Wrapped(A|B|C) and push the onAppear/onDisappear elsewhere. The Wrappers have proven to be useful in other situations and so I've kept them here.

Two protocols NavView and NavViewModel along with the class NavModel: ObservableObject offer a simple structure for building SwiftUI View hierarchies that utilize the NavigationView along with a .navigationViewStyle(StackNavigationViewStyle()). The NavModel knows about the optional Views for the hierarchy. Generally, we want to lay the Views out in a well known fashion, A before B before C or some such. These may also be optional. Perhaps A, B and C represent some SwiftUI package with reusable views. There may be occassions for configuring them into various hiearchies, like A, C or B, C or just B or just C.

protocol NavView {
    var viewModel: NavViewModel { get }
}

protocol NavViewModel : AnyObject {
    var name: String { get }
    var uuid: UUID { get }
    var selected: [String:Int?] { get set }
    var isVisible: Bool { get set }
    var navModel: NavModel { get }
    func doOnAppear(currentView: NavView, dismiss: DismissAction, toSelect: KeyedId?)
    func doOnDisappear(toNil: KeyedId?)
}

class NavModel : ObservableObject {
    
    var a: A?
    var b: B?
    var c: C?
    ...
}

The NavModel is asked to consume a NavTo upon appearing in order to execute the programmatic navigation async fashion.

.onAppear {
      Task.detached {
           await navModel.navigateOnAppear()
      }
}

The NavViewModel in this example supports a single named select key, var selected: [String:Int?] per View. These can be used to select on the View's own items or to trigger NavigationLink instances that will match on some tag. The per View selected could be used to select a list item or as in this example, a button 4 via a KeyedId:

// to select button 4 on view A
let navTo = NavTo(downTo: [
    DownTo(view: navModel.a!, ids: [KeyedId(key: "buttons", id: 4)])
])

To programmaticaly trigger the NavigationLink to a sub view B:

   NavigationLink(destination: WrappedB(navModel: vModel.navModel, toSelect: KeyedId(key: "onBAppear", id: 1)), tag: 1, selection: $vModel.selected["B"]) {
        Text("to B")
   }

An iOS App, NavTestApp ties things together for this example by setting up 3 Views, A,B and C and programmatically navigating to C upon open, while preserving all the back buttons and hierarchy for stack navigation. The navigation is guided by the [NavTo]:

        // descend to B then C
        let navTo2 = NavTo(downTo: [
            DownTo(view: navModel.a!, ids: [KeyedId(key: "B", id: 1)]),
            DownTo(view: navModel.b!, ids: [KeyedId(key: "C", id: 1)]),
            DownTo(view: navModel.c!, ids: [KeyedId(key: "C", id: 7)])
        ])

navtest's People

Contributors

supervisor194 avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.