NavigationViewKit is a NavigationView extension library for SwiftUI.

Overview

NavigationViewKit

中文版说明

NavigationViewKit is a NavigationView extension library for SwiftUI.

For more detailed documentation and demo, please visit 用NavigationViewKit增强SwiftUI的导航视图

The extension follows several principles.

  • Non-disruptive

Any new feature does not affect the native functionality provided by Swiftui, especially if it does not affect the performance of Toolbar, NavigationLink in NavigationView

  • Be as easy to use as possible

    Add new features with minimal code

  • SwiftUI native style

    Extensions should be called in the same way as the native SwiftUI as much as possible

NavigationViewManager

Introduction

One of the biggest complaints from developers about NavigationView is that it does not support a convenient means of returning to the root view. There are two commonly used solutions.

  • Repackage the UINavigationController

    A good wrapper can indeed use the many functions provided by UINavigationController, but it is very easy to conflict with the native methods in SwiftUI, so you can't have both.

  • Use procedural `NavigationLink

    Return the programmed NavigationLink (usually isActive) by undoing the root view. This means will limit the variety of NavigationLink options, plus is not conducive to implementation from non-view code.

NavigationViewManager is the navigation view manager provided in NavigationViewKit, it provides the following functions.

  • Can manage all the NavigationView in the application
  • Support to return the root view directly from any view under NavigationView by code
  • Jump to a new view via code from any view under NavigationView (no need to describe NavigationLink in the view)
  • Return to the root view via NotificatiionCenter for any NavigationView in the specified application
  • By NotificatiionCenter, let any NavigationView in the application jump to the new view
  • Support transition animation on and off

Register NavigationView

Since NavigationgViewManager supports multiple navigation views management, you need to register for each managed navigation view.

import NavigationViewKit
NavigationView {
            List(0..<10) { _ in
                NavigationLink("abc", destination: DetailView())
            }
        }
        .navigationViewManager(for: "nv1", afterBackDo: {print("back to root") })

navigationViewManager is a View extension, defined as follows.

extension View {
    public func navigationViewManager(for tag: String, afterBackDo cleanAction: @escaping () -> Void = {}) -> some View
}

for is the name (or tag) of the currently registered NavigationView, afterBackDo is the code segment executed when going to the root view.

The tag of each managed NavigationView in the application needs to be unique.

Returning to the root view from a view

In any sub-view of a registered NavigationView, the return to the root view can be achieved with the following code.

@Environment(\.navigationManager) var nvmanager         

Button("back to root view") {
    nvmanager.wrappedValue.popToRoot(tag:"nv1"){
          	 print("other back")
           }
}

popToRoot is defined as follows.

func popToRoot(tag: String, animated: Bool = true, action: @escaping () -> Void = {})

tag is the registered Tag of the current NavigationView, animated sets whether to show the transition animation when returning to the root view, and action is the further after-back code segment. This code will be executed after the registration code segment (afterBackDo) and is mainly used to pass the data in the current view.

This can be done via the

@Environment(\.currentNaviationViewName) var tag

Get the registered Tag of the current NavigationView, so that the view can be reused in different NavigtionViews.

struct DetailView: View {
    @Environment(\.navigationManager) var nvmanager
    @Environment(\.currentNaviationViewName) var tag
    var body: some View {
        VStack {
            Button("back to root view") {
                if let tag = tag {
                    nvmanager.wrappedValue.popToRoot(tag:tag,animated: false) {
                        print("other back")
                    }
                }
            }
        }
    }
}

Using NotificationCenter to return to the root view

Since the main use of NavigationViewManager in my app is to handle Deep Link, the vast majority of the time it is not called in the view code. So NavigationViewManager provides a similar method based on NotificationCenter.

In the code using :

let backToRootItem = NavigationViewManager.BackToRootItem(tag: "nv1", animated: false, action: {})
NotificationCenter.default.post(name: .NavigationViewManagerBackToRoot, object: backToRootItem)

Returns the specified NavigationView to the root view.

Jump from a view to a new view

Use :

@Environment(\.navigationManager) var nvmanager

Button("go to new View"){
        nvmanager.wrappedValue.pushView(tag:"nv1",animated: true){
            Text("New View")
                .navigationTitle("new view")
        }
}

The definition of pushView is as follows.

func pushView<V: View>(tag: String, animated: Bool = true, @ViewBuilder view: () -> V)

tag is the registered Tag of NavigationView, animation sets whether to show the transition animation, view is the new view. The view supports all definitions native to SwiftUI, such as toolbar, navigationTitle, etc.

At the moment, when transition animation is enabled, title and toolbar will be shown after the transition animation, so the view is a little bit short. I will try to fix it in the future.

Use NotificationCenter to jump to new view

In the code.

let pushViewItem = NavigationViewManager.PushViewItem(tag: "nv1", animated: false) {
                    AnyView(
                        Text("New View")
                            .navigationTitle("第四级视图")
                    )
                }
NotificationCenter.default.post(name:.NavigationViewManagerPushView, object: pushViewItem)

tag is the registered Tag of NavigationView, animation sets whether to show the transition animation, view is the new view. The view supports all definitions native to SwiftUI, such as toolbar, navigationTitle, etc.

At the moment, when transition animation is enabled, title and toolbar will be shown after the transition animation, so the view is a little bit short. I will try to fix it in the future.

Use NotificationCenter to jump to new view

In the code.

DoubleColoumnJustForPadNavigationViewStyle

DoubleColoumnJustForPadNavigationViewStyle is a modified version of DoubleColoumnNavigationViewStyle, its purpose is to improve the performance of DoubleColoumnNavigationViewStyle in landscape on iPhone Max when iPhone and iPad use the same set of code, and different from other iPhone models.

When iPhone Max is in landscape, the NavigationView will behave like iPad with double columns, which makes the application behave inconsistently on different iPhones.

When using DoubleColoumnJustForPadNavigationViewStyle, iPhone Max will still show StackNavigationViewStyle in landscape.

Usage.

NavigationView{
   ...
}
.navigationViewStyle(DoubleColoumnJustForPadNavigationViewStyle())

It can be used directly under swift 5.5

.navigationViewStyle(.columnsForPad)

TipOnceDoubleColumnNavigationViewStyle

The current DoubleColumnNavigationViewStyle behaves differently on iPad in both horizontal and vertical screens. When the screen is vertical, the left column is hidden by default, making it easy for new users to get confused.

TipOnceDoubleColumnNavigationViewStyle will show the left column above the right column to remind the user when the iPad is in vertical screen for the first time. This reminder will only happen once. If you rotate the orientation after the reminder, the reminder will not be triggered again when you enter the vertical screen again.

NavigationView{
   ...
}
.navigationViewStyle(TipOnceDoubleColumnNavigationViewStyle())

It can be used directly under swift 5.5

.navigationViewStyle(.tipColumns)

FixDoubleColumnNavigationViewStyle

In Health Notes, I want the iPad version to always keep two columns displayed no matter in landscape or portrait, and the left column cannot be hidden.

I previously used HStack set of two NavigationView to achieve this effect

Now, the above effect can be easily achieved by FixDoubleColumnNavigationViewStyle in NavigationViewKit directly.

NavigationView{
   ...
}
.navigationViewStyle(FixDoubleColumnNavigationViewStyle(widthForLandscape: 350, widthForPortrait:250))

And you can set the left column width separately for both landscape and portrait states.

For more detailed documentation and demo, please visit My Blog

You might also like...
FlowStacks allows you to hoist SwiftUI navigation and presentation state into a Coordinator

FlowStacks allow you to manage complex SwiftUI navigation and presentation flows with a single piece of state. This makes it easy to hoist that state into a high-level coordinator view. Using this pattern, you can write isolated views that have zero knowledge of their context within the navigation flow of an app.

Change SwiftUI Navigation Bar Color for different View
Change SwiftUI Navigation Bar Color for different View

SwiftUINavigationBarColor Change SwiftUI NavigationBar background color per screen. Usage For NavigationBarColor to work, you have to set the Navigati

Path based routing in SwiftUI

Easy and maintainable app navigation with path based routing for SwiftUI. With SwiftUI Router you can power your SwiftUI app with path based routing.

Coordinators in SwiftUI. Simple, powerful and elegant.
Coordinators in SwiftUI. Simple, powerful and elegant.

Simple, powerful and elegant implementation of the Coordinator pattern in SwiftUI. Stinsen is written using 100% SwiftUI which makes it work seamlessl

🧭 SwiftUI navigation done right

🧭 NavigationKit NavigationKit is a lightweight library which makes SwiftUI navigation super easy to use. 💻 Installation 📦 Swift Package Manager Usi

Navigation helpers for SwiftUI applications build with ComposableArchitecture
Navigation helpers for SwiftUI applications build with ComposableArchitecture

Swift Composable Presentation 📝 Description Navigation helpers for SwiftUI applications build with ComposableArchitecture. More info about the concep

Make SwiftUI Navigation be easy

VNavigator VNavigator is a clean and easy-to-use navigation in SwiftUI base on UINavigationController in UIKit Installation From CocoaPods CocoaPods i

Tools for making SwiftUI navigation simpler, more ergonomic and more precise.
Tools for making SwiftUI navigation simpler, more ergonomic and more precise.

SwiftUI Navigation Tools for making SwiftUI navigation simpler, more ergonomic and more precise. Motivation Tools Navigation overloads Navigation view

SwiftUINavigation provides UIKit-like navigation in SwiftUI

SwiftUINavigation About SwiftUINavigation provides UIKit-like navigation in Swif

Comments
  • iOS 14 Error

    iOS 14 Error

    My app works correctly with NavigationViewKit in iOS 15 but crashes with the following in iOS 14 simulator and device. App works in iOS 14 without NavigationViewKit. Anything I can try to resolve?

    dyld: Symbol not found: _$s6_Body27SwiftUI19NavigationViewStylePTl Referenced from: /private/var/containers/Bundle/Application/AFD042A3-C3E5-490B-9E04-D293FE66EFCD/TheApp.app/TheApp Expected in: /System/Library/Frameworks/SwiftUI.framework/SwiftUI in /private/var/containers/Bundle/Application/AFD042A3-C3E5-490B-9E04-D293FE66EFCD/TheApp.app/TheApp dyld: launch, loading dependent libraries DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib

    opened by dmholmes 4
  • 作者你好,想请教一个路由跳转的问题

    作者你好,想请教一个路由跳转的问题

    需求是这样:PageA -> PageB -> PageC,此时跳转PageD,但是PageB、PageC 都要退出,即变为PageA -> PageD; 现在实现的方法是以PageA为root,popToRoot 后,再pushView(tag: "root"){ PageD()} ,这样虽然可以实现,但是会有一个先切回到PageA的过程,请问有没有其他实现方法呢

    opened by BugMonkey 3
  • 将Sources内的文件导进项目build的后,报错 : Function builder attribute 'ViewBuilder' can only be applied to a property if it defines a getter

    将Sources内的文件导进项目build的后,报错 : Function builder attribute 'ViewBuilder' can only be applied to a property if it defines a getter

    报错文件名:NavigationViewManager.swift

    具体报错位置:@ViewBuilder var view: () -> AnyView

       public init(tag: String, animated: Bool, view: @escaping () -> AnyView) {
            self.tag = tag
            self.animated = animated
            self.view = view
        }
    
        let tag: String
        let animated: Bool
        @ViewBuilder var view: () -> AnyView  // build后,这里报错:Function builder attribute 'ViewBuilder' can only be applied to a property if it defines a getter
    }
    

    Swift版本:5.3 工具版本:XCode 12 系统:Catalina 10.15.5

    opened by AganYa 3
Releases(0.0.5)
Owner
东坡肘子
家庭煮夫.专业带娃. 微信公共号: 肘子的Swift记事本
东坡肘子
Custom navigation swiftui NavigationLink NavigationView

Custom navigation swiftui Experimenting with navigation link. if you find this idea interesting you can take and expend it into a more powerful soluti

Igor 5 Dec 2, 2022
A wrapper for NavigationView and NavigationLink that makes programmatic navigation a little friendlier.

NavigatorKit A wrapper for NavigationView and NavigationLink that makes programmatic navigation a little friendlier. NavigatorKit is an opinionated wr

Gyuri Grell 2 Jun 16, 2022
iOS UI library to show and hide an extension to your UINavigationBar

ADNavigationBarExtension is a UI library written in Swift. It allows you to show and hide an extension to your UINavigationBar Features Use Extensible

FABERNOVEL 58 Aug 29, 2022
A UINavigationBar extension to show loading effects

BusyNavigationBar A UINavigationBar extension to show loading effects above navigation bar's background. Screenshot Stripes Bars Your custom layer Usa

Günay Mert Karadoğan 992 Dec 3, 2022
An open source library for building deep-linkable SwiftUI applications with composition, testing and ergonomics in mind

Composable Navigator An open source library for building deep-linkable SwiftUI applications with composition, testing and ergonomics in mind Vanilla S

Bahn-X 539 Jan 8, 2023
Router is a library that assists with SwiftUI view transitions.

Router Router is a library that assists with SwiftUI view transitions. Installation .package(name: "Router", url: "[email protected]:1amageek/Router.git"

1amageek 69 Dec 23, 2022
SwiftUINavigator: a lightweight, flexible, and super easy library which makes SwiftUI navigation a trivial task

The logo is contributed with ❤️ by Mahmoud Hussein SwiftUINavigator is a lightwe

OpenBytes 22 Dec 21, 2022
A drop-in universal library helps you to manage the navigation bar styles and makes transition animations smooth between different navigation bar styles

A drop-in universal library helps you to manage the navigation bar styles and makes transition animations smooth between different navigation bar styles while pushing or popping a view controller for all orientations. And you don't need to write any line of code for it, it all happens automatically.

Zhouqi Mo 3.3k Dec 21, 2022
custom navigationBar in swiftui

SwiftUI-WRNavigationBar custom navigationBar in swiftui Requirements iOS 14.0 Installation pod 'SwiftUI-WRNavigationBar', '~>1.1.1' Overview debug cus

wangrui460 29 Nov 7, 2022
sRouting - The lightweight navigation framework for SwiftUI.

sRouting The lightweight navigation framework for SwiftUI. Overview sRouting using the native navigation mechanism in SwiftUI. It's easy to handle nav

Shiro 8 Aug 15, 2022