Easy-to-use segues in SwiftUI, allowing for presenting views using common UIKIt Segue types - push, modal and popover

Overview

SwiftUI Segues

Easy-to-use segues in SwiftUI, allowing for presenting views using common UIKIt Segue types - push, modal and popover.

Preview

Navigating between views/screens in SwiftUI is more difficult and convoluted than it is in UIKit, with different segues dispersed over multiple views (e.g, NavigationLink) and modifiers (popover, fullScreenCover). Moreover, part of this functionality isn't available on iOS 13.

This package contains two View Modifiers that allow for seamless integration of segues into your SwiftUI code, and it's fully compatible with iOS 13 and above. The segues are triggered by setting binding values, and can be dismissed by setting the value to nil. Yep, it's as easy as this:

.segue(.push, tag: .pushTest, selection: $route) {
    Text("Welcome to Push")
}

Installation

This component is distributed as a Swift package. Just add this repo's URL to XCode:

https://github.com/globulus/swiftui-segues

How to use

  • A good SwiftUI navigation practice is to define all routes, i.e transitions from the current view to subsequent ones, in an enum. Then, add a @State var to your view (or @Published var in your VM) whose value is an optional enum route. This is consistent with the tag/selection and item variants of NavigationLink / Popover / FullScreenCover.
  • Assign a value to the route binding to trigger a segue, and assign it to nil to dismiss it.

Mixed segues

To add a single segue of a certain type that's triggered when its route binding (selection)'s value is set to a certain tag, use the segue modifier. Specify its destination view in the view builder block:

struct MixedSegueTest: View {
    // All the routes that lead from this view to the next ones
    enum Route: Hashable {
        case pushTest, modalTest, popoverTest
    }
    
    // Triggers segues when its values are changes
    @State private var route: Route? = nil
    
    var body: some View {
        NavigationView {
            VStack(spacing: 20) {
                Button("Push") {
                    // Navigate by setting route values
                    route = .pushTest
                }
                Button("Modal") {
                    route = .modalTest
                }
                Button("Popover") {
                    route = .popoverTest
                }
            }
            .navigationBarTitle("SwiftUI Segues", displayMode: .inline)
            
            // Here are individual, mixed segues, with their destinations
            .segue(.push, tag: .pushTest, selection: $route) {
                Text("Welcome to Push")
            }
            .segue(.modal, tag: .modalTest, selection: $route) {
                Button("Welcome to modal") {
                    route = nil
                }
            }
            .segue(.popover(.rect(.bounds), .top), tag: .popoverTest, selection: $route) {
                Text("Welcome to Popover")
            }
        }
    }
}

Multiple segues of the same type

If all the segues bound to the same selection are of the same type (push, modal or popover), use the segues modifier:

struct PushSegueTest: View {
    @State private var route: Route? = nil
    
    var body: some View {
        NavigationView {
            VStack {
                Button("Go to A") {
                    route = .a
                }
                Button("Go to B") {
                    route = .b
                }
                Button("Go to C") {
                    route = .c
                }
            }
            .segues(.push, selection: $route) { route in
                switch route {
                case .a:
                    Text("A")
                case .b:
                    Text("B")
                case .c:
                    Text("C")
                }
            }
        }
    }
    
    enum Route: Identifiable, CaseIterable, Hashable {
        case a, b, c
        
        var id: String {
            "\(self)"
        }
    }
}

struct ModalSegueTest: View {
    @State private var route: Route? = nil
    
    var body: some View {
        VStack {
            Button("Go to A") {
                route = .a
            }
            Button("Go to B") {
                route = .b
            }
            Button("Go to C") {
                route = .c
            }
        }
        .segues(.modal, selection: $route) { route in
            switch route {
            case .a:
                Button("A") {
                    self.route = nil // dismissed the segue
                }
            case .b:
                Button("B") {
                    self.route = nil
                }
            case .c:
                Button("C") {
                    self.route = nil
                }
            }
        }
    }
    
    enum Route: Identifiable, CaseIterable, Hashable {
        case a, b, c
        
        var id: String {
            "\(self)"
        }
    }
}

Recipe

Check out this recipe for in-depth description of the component and its code. Check out SwiftUIRecipes.com for more SwiftUI recipes!

Changelog

  • 1.0.0 - Initial release.
You might also like...
SwiftyXPC - a wrapper for Apple’s XPC interprocess communication library that gives it an easy-to-use, idiomatic Swift interface.

SwiftyXPC is a wrapper for Apple’s XPC interprocess communication library that gives it an easy-to-use, idiomatic Swift interface.

XCode Preview template for UIkit based project.
XCode Preview template for UIkit based project.

SwiftPreview XCode Preview template for UIkit based project. Support custom file template class inherit from UIView and UIViewController. How to use?

UIKit-based app project template for Swift Playgrounds 4
UIKit-based app project template for Swift Playgrounds 4

playgrounds-uikit-app This is a simplistic sample template for Swift Playgrounds 4 to begin with a UIKit-based app delegate & window scene instead of

This provides a bridge to use Sync with Tokamak instead of SwiftUI
This provides a bridge to use Sync with Tokamak instead of SwiftUI

Sync Tokamak This provides a bridge to use Sync with Tokamak instead of SwiftUI.

Create an easy to peek SwiftUI View to showcase your own data, catalog, images, or anything you'd like.
Create an easy to peek SwiftUI View to showcase your own data, catalog, images, or anything you'd like.

Create an easy to peek SwiftUI View to showcase your own data, catalog, images, or anything you'd like.

TagKit makes it easy to create tag-based apps in SwiftUI.
TagKit makes it easy to create tag-based apps in SwiftUI.

About TagKit TagKit makes it easy to work with tags in Swift and SwiftUI. The result can look like this or completely different: Tags and tag views ca

BioViewer - Protein (.pdb, .cif and .fasta) viewer for iPhone, iPad and Mac, using SwiftUI + SceneKit
BioViewer - Protein (.pdb, .cif and .fasta) viewer for iPhone, iPad and Mac, using SwiftUI + SceneKit

BioViewer - Protein (.pdb, .cif and .fasta) viewer for iPhone, iPad and Mac, using SwiftUI + SceneKit

A repository to experiment around the use and generation of tokens for the JLL/T Design System

Basic Style Dictionary This example code is bare-bones to show you what this framework can do. If you have the style-dictionary module installed globa

A zero-code template app that demonstrates how to use TheraForge's APIs and can be used for fast prototyping
A zero-code template app that demonstrates how to use TheraForge's APIs and can be used for fast prototyping

TheraForge MagicBox 1.0.0-beta The Open TheraForge (OTF) MagicBox app is a template for creating digital health solutions that help people better mana

Owner
Gordan Glavaš
Gordan Glavaš
A common use case is wanting to convert device identifiers such as iPhone10,1 to a user friendly name; iPhone 8.

Devices Swift package that contains all devices from https://www.theiphonewiki.com/wiki/Models. A common use case is wanting to convert device identif

null 17 Nov 28, 2022
An example implementation of using a native iOS Notification Service Extension (to display images in remote push notification) in Titanium.

Titanium iOS Notification Service Extension An example implementation of using a native iOS Notification Service Extension (to display images in remot

Hans Knöchel 8 Nov 21, 2022
A Collection of PropertyWrappers to make custom Serialization of Swift Codable Types easy

CodableWrappers Simplified Serialization with Property Wrappers Move your Codable and (En/De)coder customization to annotations! struct YourType: Coda

null 393 Jan 5, 2023
A simple, reliable and scalable delivery API for transactional push notifications for websites and applications

Catapush is a simple, reliable and scalable delivery API for transactional push notifications for websites and applications. Ideal for sending data-dr

Catapush 0 Dec 29, 2021
A collection of common diagnostics and debugging utilities.

KippleDiagnostics A collection of common diagnostics and debugging utilities. ⚠️ The code in this library has been made public as-is for the purposes

Kipple 10 Sep 2, 2022
An experimental functional programming language with dependent types, inspired by Swift and Idris.

Kara An experimental functional programming language with dependent types, inspired by Swift and Idris. Motivation Development of Kara is motivated by

null 40 Sep 17, 2022
UIEnvironment - A framework that mimics the SwiftUI view's environment to replicate the value distribution thought your UIKit app.

A framework that mimics the SwiftUI view's environment to replicate the value distribution thought your UIKit view hierarchy. Overview D

Łukasz Śliwiński 15 Dec 5, 2022
Are you sure the chemical compounds of your daily use are 100% safe? Use Chem-Aware, identify them right now!

View Project On Devpost: Built With: PubChem's REST API How To Install Chem Aware: Prerequiste: Latest Version of Xcode and Simulators installed The a

Jerry Zhang 5 Aug 23, 2022
Mimicrated views and controls to native Apple appearance.

Mimicrated views and controls to native Apple appearance. If you have any ideas of what elements can be added, let me know. Below you will see previews of all the elements and how to use them.

Ivan Vorobei 85 Dec 3, 2022
Goal: Create an iOS app with two views, MainViewController and DetailViewController

Goal: Create an iOS app with two views, MainViewController and DetailViewController

Jesse Rae 0 Jan 23, 2022