├── README.md
├── RouterWithNavigationStack
├── Assets.xcassets
│ ├── Contents.json
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
├── Router
│ ├── ViewSpec.swift
│ ├── RoutingView.swift
│ ├── View+Modal.swift
│ └── Router.swift
├── AlertView.swift
├── RouterWithNavigationStackApp.swift
├── MainView.swift
├── DetailView.swift
├── ListView.swift
└── MainRouter.swift
├── RouterWithNavigationStack.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── project.pbxproj
├── LICENSE
└── .gitignore
/README.md:
--------------------------------------------------------------------------------
1 | # Routing-in-SwiftUI-with-NavigationStack
--------------------------------------------------------------------------------
/RouterWithNavigationStack/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/Router/ViewSpec.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewSpec.swift
3 | // RouterWithNavigationStack
4 | //
5 | // Created by Ihor Vovk on 07/02/2023.
6 | //
7 |
8 | import Foundation
9 |
10 | enum ViewSpec: Equatable, Hashable {
11 |
12 | case main
13 | case list
14 | case detail(String)
15 | case alert
16 | }
17 |
18 | extension ViewSpec: Identifiable {
19 |
20 | var id: Self { self }
21 | }
22 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/AlertView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AlertView.swift
3 | // RouterWithNavigationStack
4 | //
5 | // Created by Ihor Vovk on 08/02/2023.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct AlertView: View {
11 |
12 | var body: some View {
13 | Text("Alert")
14 | .padding(.vertical, 20)
15 | }
16 | }
17 |
18 | struct AlertView_Previews: PreviewProvider {
19 |
20 | static var previews: some View {
21 | AlertView()
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/RouterWithNavigationStackApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RouterWithNavigationStackApp.swift
3 | // RouterWithNavigationStack
4 | //
5 | // Created by Ihor Vovk on 07/02/2023.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @main
11 | struct RouterWithNavigationStackApp: App {
12 |
13 | @StateObject private var router = MainRouter(isPresented: .constant(.main))
14 |
15 | var body: some Scene {
16 |
17 | WindowGroup {
18 | MainView(router: router)
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/MainView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MainView.swift
3 | // RouterWithNavigationStack
4 | //
5 | // Created by Ihor Vovk on 07/02/2023.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct MainView: View {
11 |
12 | @StateObject private var router: MainRouter
13 |
14 | init(router: MainRouter) {
15 | _router = StateObject(wrappedValue: router)
16 | }
17 |
18 | var body: some View {
19 | RoutingView(router: router) {
20 | VStack {
21 | Spacer()
22 | Button("Present List") {
23 | router.presentList()
24 | }
25 |
26 | Spacer()
27 | }
28 | }
29 | }
30 | }
31 |
32 | struct MainView_Previews: PreviewProvider {
33 |
34 | static var previews: some View {
35 | MainView(router: MainRouter(isPresented: .constant(.main)))
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/DetailView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailView.swift
3 | // RouterWithNavigationStack
4 | //
5 | // Created by Ihor Vovk on 08/02/2023.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct DetailView: View {
11 |
12 | private let description: String
13 | @StateObject private var router: MainRouter
14 |
15 | init(description: String, router: MainRouter) {
16 | self.description = description
17 | _router = StateObject(wrappedValue: router)
18 | }
19 |
20 | var body: some View {
21 | VStack(spacing: 20) {
22 | Text(description)
23 | Button("Present Alert") {
24 | router.presentAlert()
25 | }
26 | }
27 | }
28 | }
29 |
30 | struct DetailView_Previews: PreviewProvider {
31 |
32 | static var previews: some View {
33 | DetailView(description: "Description", router: MainRouter(isPresented: .constant(.detail("Details"))))
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Ihor Vovk
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/Router/RoutingView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RoutingView.swift
3 | // RouterWithNavigationStack
4 | //
5 | // Created by Ihor Vovk on 07/02/2023.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct RoutingView: View {
11 |
12 | @StateObject var router: Router
13 | private let content: Content
14 |
15 | init(router: Router, @ViewBuilder content: @escaping () -> Content) {
16 | _router = StateObject(wrappedValue: router)
17 | self.content = content()
18 | }
19 |
20 | var body: some View {
21 | NavigationStack(path: router.navigationPath) {
22 | content
23 | .navigationDestination(for: ViewSpec.self) { spec in
24 | router.view(spec: spec, route: .navigation)
25 | }
26 | }.sheet(item: router.presentingSheet) { spec in
27 | router.view(spec: spec, route: .sheet)
28 | }.fullScreenCover(item: router.presentingFullScreen) { spec in
29 | router.view(spec: spec, route: .fullScreenCover)
30 | }.modal(item: router.presentingModal) { spec in
31 | router.view(spec: spec, route: .modal)
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/ListView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListView.swift
3 | // RouterWithNavigationStack
4 | //
5 | // Created by Ihor Vovk on 08/02/2023.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct ListView: View {
11 |
12 | @StateObject private var router: MainRouter
13 |
14 | init(router: MainRouter) {
15 | _router = StateObject(wrappedValue: router)
16 | }
17 |
18 | var body: some View {
19 | RoutingView(router: router) {
20 | VStack(spacing: 20) {
21 | ForEach(1..<4) {
22 | cell(index: $0)
23 | }
24 | }.toolbar {
25 | ToolbarItem(placement: .navigationBarLeading) {
26 | Button {
27 | router.dismiss()
28 | } label: {
29 | Image(systemName: "xmark.circle")
30 | }
31 | }
32 | }
33 | }
34 | }
35 | }
36 |
37 | private extension ListView {
38 |
39 | func cell(index: Int) -> some View {
40 | Button("Item \(index)") {
41 | router.presentDetail(description: "Description \(index)")
42 | }
43 | }
44 | }
45 |
46 | struct ListView_Previews: PreviewProvider {
47 |
48 | static var previews: some View {
49 | ListView(router: MainRouter(isPresented: .constant(.list)))
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/Router/View+Modal.swift:
--------------------------------------------------------------------------------
1 | //
2 | // View+Modal.swift
3 | // RouterWithNavigationStack
4 | //
5 | // Created by Ihor Vovk on 07/02/2023.
6 | //
7 |
8 | import SwiftUI
9 |
10 | extension View {
11 |
12 | func modal- (item: Binding
- , onDismiss: (() -> Void)? = nil, content: @escaping (Item) -> Content) -> some View where Item: Identifiable, Content: View {
13 | ZStack(alignment: .center) {
14 | self
15 | if let wrappedItem = item.wrappedValue {
16 | Color.black.opacity(0.5)
17 | .ignoresSafeArea()
18 | VStack(spacing: 0) {
19 | HStack {
20 | Button {
21 | item.wrappedValue = nil
22 | } label: {
23 | Image(systemName: "xmark.circle")
24 | }
25 |
26 | Spacer()
27 | }.frame(height: 50)
28 | .padding(.horizontal, 12)
29 |
30 | Divider()
31 | content(wrappedItem)
32 | }.clipShape(RoundedRectangle(cornerRadius: 8))
33 | .background(
34 | RoundedRectangle(cornerRadius: 8)
35 | .foregroundColor(.white)
36 | ).padding(.horizontal, 16)
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/MainRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MainRouter.swift
3 | // RouterWithNavigationStack
4 | //
5 | // Created by Ihor Vovk on 08/02/2023.
6 | //
7 |
8 | import SwiftUI
9 |
10 | class MainRouter: Router {
11 |
12 | func presentList() {
13 | presentSheet(.list)
14 | }
15 |
16 | func presentDetail(description: String) {
17 | navigateTo(.detail(description))
18 | }
19 |
20 | func presentAlert() {
21 | presentModal(.alert)
22 | }
23 |
24 | override func view(spec: ViewSpec, route: Route) -> AnyView {
25 | AnyView(buildView(spec: spec, route: route))
26 | }
27 | }
28 |
29 | private extension MainRouter {
30 |
31 | @ViewBuilder
32 | func buildView(spec: ViewSpec, route: Route) -> some View {
33 | switch spec {
34 | case .list:
35 | ListView(router: router(route: route))
36 | case .detail(let description):
37 | DetailView(description: description, router: router(route: route))
38 | case .alert:
39 | AlertView()
40 | default:
41 | EmptyView()
42 | }
43 | }
44 |
45 | func router(route: Route) -> MainRouter {
46 | switch route {
47 | case .navigation:
48 | return self
49 | case .sheet:
50 | return MainRouter(isPresented: presentingSheet)
51 | case .fullScreenCover:
52 | return MainRouter(isPresented: presentingFullScreen)
53 | case .modal:
54 | return self
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
9 | *.xcscmblueprint
10 | *.xccheckout
11 |
12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
13 | build/
14 | DerivedData/
15 | *.moved-aside
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 |
28 | ## App packaging
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | ## Playgrounds
34 | timeline.xctimeline
35 | playground.xcworkspace
36 |
37 | # Swift Package Manager
38 | #
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | # Packages/
41 | # Package.pins
42 | # Package.resolved
43 | # *.xcodeproj
44 | #
45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
46 | # hence it is not needed unless you have added a package configuration file to your project
47 | # .swiftpm
48 |
49 | .build/
50 |
51 | # CocoaPods
52 | #
53 | # We recommend against adding the Pods directory to your .gitignore. However
54 | # you should judge for yourself, the pros and cons are mentioned at:
55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
56 | #
57 | # Pods/
58 | #
59 | # Add this line if you want to avoid checking in source code from the Xcode workspace
60 | # *.xcworkspace
61 |
62 | # Carthage
63 | #
64 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
65 | # Carthage/Checkouts
66 |
67 | Carthage/Build/
68 |
69 | # Accio dependency management
70 | Dependencies/
71 | .accio/
72 |
73 | # fastlane
74 | #
75 | # It is recommended to not store the screenshots in the git repo.
76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
77 | # For more information about the recommended setup visit:
78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
79 |
80 | fastlane/report.xml
81 | fastlane/Preview.html
82 | fastlane/screenshots/**/*.png
83 | fastlane/test_output
84 |
85 | # Code Injection
86 | #
87 | # After new code Injection tools there's a generated folder /iOSInjectionProject
88 | # https://github.com/johnno1962/injectionforxcode
89 |
90 | iOSInjectionProject/
91 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack/Router/Router.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Router.swift
3 | // RouterWithNavigationStack
4 | //
5 | // Created by Ihor Vovk on 07/02/2023.
6 | //
7 |
8 | import SwiftUI
9 |
10 | class Router: ObservableObject {
11 |
12 | enum Route {
13 | case navigation
14 | case sheet
15 | case fullScreenCover
16 | case modal
17 | }
18 |
19 | struct State {
20 | var navigationPath: [ViewSpec] = []
21 | var presentingSheet: ViewSpec? = nil
22 | var presentingFullScreen: ViewSpec? = nil
23 | var presentingModal: ViewSpec? = nil
24 | var isPresented: Binding
25 |
26 | var isPresenting: Bool {
27 | presentingSheet != nil || presentingFullScreen != nil || presentingModal != nil
28 | }
29 | }
30 |
31 | @Published private(set) var state: State
32 |
33 | init(isPresented: Binding) {
34 | state = State(isPresented: isPresented)
35 | }
36 |
37 | func view(spec: ViewSpec, route: Route) -> AnyView {
38 | AnyView(EmptyView())
39 | }
40 | }
41 |
42 | extension Router {
43 |
44 | func navigateTo(_ viewSpec: ViewSpec) {
45 | state.navigationPath.append(viewSpec)
46 | }
47 |
48 | func navigateBack() {
49 | state.navigationPath.removeLast()
50 | }
51 |
52 | func replaceNavigationStack(path: [ViewSpec]) {
53 | state.navigationPath = path
54 | }
55 |
56 | func presentSheet(_ viewSpec: ViewSpec) {
57 | state.presentingSheet = viewSpec
58 | }
59 |
60 | func presentFullScreen(_ viewSpec: ViewSpec) {
61 | state.presentingFullScreen = viewSpec
62 | }
63 |
64 | func presentModal(_ viewSpec: ViewSpec) {
65 | state.presentingModal = viewSpec
66 | }
67 |
68 | func dismiss() {
69 | if state.presentingSheet != nil {
70 | state.presentingSheet = nil
71 | } else if state.presentingFullScreen != nil {
72 | state.presentingFullScreen = nil
73 | } else if state.presentingModal != nil {
74 | state.presentingModal = nil
75 | } else if navigationPath.count > 1 {
76 | state.navigationPath.removeLast()
77 | } else {
78 | state.isPresented.wrappedValue = nil
79 | }
80 | }
81 | }
82 |
83 | extension Router {
84 |
85 | var navigationPath: Binding<[ViewSpec]> {
86 | binding(keyPath: \.navigationPath)
87 | }
88 |
89 | var presentingSheet: Binding {
90 | binding(keyPath: \.presentingSheet)
91 | }
92 |
93 | var presentingFullScreen: Binding {
94 | binding(keyPath: \.presentingFullScreen)
95 | }
96 |
97 | var presentingModal: Binding {
98 | binding(keyPath: \.presentingModal)
99 | }
100 |
101 | var isPresented: Binding {
102 | state.isPresented
103 | }
104 | }
105 |
106 | private extension Router {
107 |
108 | func binding(keyPath: WritableKeyPath) -> Binding {
109 | Binding(
110 | get: { self.state[keyPath: keyPath] },
111 | set: { self.state[keyPath: keyPath] = $0 }
112 | )
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/RouterWithNavigationStack.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 56;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 00256F892992DB57000AD09A /* RouterWithNavigationStackApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00256F882992DB57000AD09A /* RouterWithNavigationStackApp.swift */; };
11 | 00256F8B2992DB57000AD09A /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00256F8A2992DB57000AD09A /* MainView.swift */; };
12 | 00256F8D2992DB58000AD09A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 00256F8C2992DB58000AD09A /* Assets.xcassets */; };
13 | 00256F902992DB58000AD09A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 00256F8F2992DB58000AD09A /* Preview Assets.xcassets */; };
14 | 00256F982992DBBA000AD09A /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00256F972992DBBA000AD09A /* Router.swift */; };
15 | 00256F9A2992DBCF000AD09A /* RoutingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00256F992992DBCF000AD09A /* RoutingView.swift */; };
16 | 00256F9C2992DBF7000AD09A /* ViewSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00256F9B2992DBF7000AD09A /* ViewSpec.swift */; };
17 | 00256F9E2992DEC9000AD09A /* View+Modal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00256F9D2992DEC9000AD09A /* View+Modal.swift */; };
18 | 00256FA429943028000AD09A /* MainRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00256FA329943028000AD09A /* MainRouter.swift */; };
19 | 00256FA629943130000AD09A /* ListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00256FA529943130000AD09A /* ListView.swift */; };
20 | 00256FA8299431FF000AD09A /* DetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00256FA7299431FF000AD09A /* DetailView.swift */; };
21 | 00256FAA29943850000AD09A /* AlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00256FA929943850000AD09A /* AlertView.swift */; };
22 | /* End PBXBuildFile section */
23 |
24 | /* Begin PBXFileReference section */
25 | 00256F852992DB57000AD09A /* RouterWithNavigationStack.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RouterWithNavigationStack.app; sourceTree = BUILT_PRODUCTS_DIR; };
26 | 00256F882992DB57000AD09A /* RouterWithNavigationStackApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterWithNavigationStackApp.swift; sourceTree = ""; };
27 | 00256F8A2992DB57000AD09A /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = ""; };
28 | 00256F8C2992DB58000AD09A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
29 | 00256F8F2992DB58000AD09A /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
30 | 00256F972992DBBA000AD09A /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = ""; };
31 | 00256F992992DBCF000AD09A /* RoutingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoutingView.swift; sourceTree = ""; };
32 | 00256F9B2992DBF7000AD09A /* ViewSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewSpec.swift; sourceTree = ""; };
33 | 00256F9D2992DEC9000AD09A /* View+Modal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Modal.swift"; sourceTree = ""; };
34 | 00256FA329943028000AD09A /* MainRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainRouter.swift; sourceTree = ""; };
35 | 00256FA529943130000AD09A /* ListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListView.swift; sourceTree = ""; };
36 | 00256FA7299431FF000AD09A /* DetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailView.swift; sourceTree = ""; };
37 | 00256FA929943850000AD09A /* AlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertView.swift; sourceTree = ""; };
38 | /* End PBXFileReference section */
39 |
40 | /* Begin PBXFrameworksBuildPhase section */
41 | 00256F822992DB57000AD09A /* Frameworks */ = {
42 | isa = PBXFrameworksBuildPhase;
43 | buildActionMask = 2147483647;
44 | files = (
45 | );
46 | runOnlyForDeploymentPostprocessing = 0;
47 | };
48 | /* End PBXFrameworksBuildPhase section */
49 |
50 | /* Begin PBXGroup section */
51 | 00256F7C2992DB57000AD09A = {
52 | isa = PBXGroup;
53 | children = (
54 | 00256F872992DB57000AD09A /* RouterWithNavigationStack */,
55 | 00256F862992DB57000AD09A /* Products */,
56 | );
57 | sourceTree = "";
58 | };
59 | 00256F862992DB57000AD09A /* Products */ = {
60 | isa = PBXGroup;
61 | children = (
62 | 00256F852992DB57000AD09A /* RouterWithNavigationStack.app */,
63 | );
64 | name = Products;
65 | sourceTree = "";
66 | };
67 | 00256F872992DB57000AD09A /* RouterWithNavigationStack */ = {
68 | isa = PBXGroup;
69 | children = (
70 | 00256F962992DBAD000AD09A /* Router */,
71 | 00256F882992DB57000AD09A /* RouterWithNavigationStackApp.swift */,
72 | 00256FA329943028000AD09A /* MainRouter.swift */,
73 | 00256F8A2992DB57000AD09A /* MainView.swift */,
74 | 00256FA529943130000AD09A /* ListView.swift */,
75 | 00256FA7299431FF000AD09A /* DetailView.swift */,
76 | 00256FA929943850000AD09A /* AlertView.swift */,
77 | 00256F8C2992DB58000AD09A /* Assets.xcassets */,
78 | 00256F8E2992DB58000AD09A /* Preview Content */,
79 | );
80 | path = RouterWithNavigationStack;
81 | sourceTree = "";
82 | };
83 | 00256F8E2992DB58000AD09A /* Preview Content */ = {
84 | isa = PBXGroup;
85 | children = (
86 | 00256F8F2992DB58000AD09A /* Preview Assets.xcassets */,
87 | );
88 | path = "Preview Content";
89 | sourceTree = "";
90 | };
91 | 00256F962992DBAD000AD09A /* Router */ = {
92 | isa = PBXGroup;
93 | children = (
94 | 00256F972992DBBA000AD09A /* Router.swift */,
95 | 00256F992992DBCF000AD09A /* RoutingView.swift */,
96 | 00256F9B2992DBF7000AD09A /* ViewSpec.swift */,
97 | 00256F9D2992DEC9000AD09A /* View+Modal.swift */,
98 | );
99 | path = Router;
100 | sourceTree = "";
101 | };
102 | /* End PBXGroup section */
103 |
104 | /* Begin PBXNativeTarget section */
105 | 00256F842992DB57000AD09A /* RouterWithNavigationStack */ = {
106 | isa = PBXNativeTarget;
107 | buildConfigurationList = 00256F932992DB58000AD09A /* Build configuration list for PBXNativeTarget "RouterWithNavigationStack" */;
108 | buildPhases = (
109 | 00256F812992DB57000AD09A /* Sources */,
110 | 00256F822992DB57000AD09A /* Frameworks */,
111 | 00256F832992DB57000AD09A /* Resources */,
112 | );
113 | buildRules = (
114 | );
115 | dependencies = (
116 | );
117 | name = RouterWithNavigationStack;
118 | productName = RouterWithNavigationStack;
119 | productReference = 00256F852992DB57000AD09A /* RouterWithNavigationStack.app */;
120 | productType = "com.apple.product-type.application";
121 | };
122 | /* End PBXNativeTarget section */
123 |
124 | /* Begin PBXProject section */
125 | 00256F7D2992DB57000AD09A /* Project object */ = {
126 | isa = PBXProject;
127 | attributes = {
128 | BuildIndependentTargetsInParallel = 1;
129 | LastSwiftUpdateCheck = 1410;
130 | LastUpgradeCheck = 1410;
131 | TargetAttributes = {
132 | 00256F842992DB57000AD09A = {
133 | CreatedOnToolsVersion = 14.1;
134 | };
135 | };
136 | };
137 | buildConfigurationList = 00256F802992DB57000AD09A /* Build configuration list for PBXProject "RouterWithNavigationStack" */;
138 | compatibilityVersion = "Xcode 14.0";
139 | developmentRegion = en;
140 | hasScannedForEncodings = 0;
141 | knownRegions = (
142 | en,
143 | Base,
144 | );
145 | mainGroup = 00256F7C2992DB57000AD09A;
146 | productRefGroup = 00256F862992DB57000AD09A /* Products */;
147 | projectDirPath = "";
148 | projectRoot = "";
149 | targets = (
150 | 00256F842992DB57000AD09A /* RouterWithNavigationStack */,
151 | );
152 | };
153 | /* End PBXProject section */
154 |
155 | /* Begin PBXResourcesBuildPhase section */
156 | 00256F832992DB57000AD09A /* Resources */ = {
157 | isa = PBXResourcesBuildPhase;
158 | buildActionMask = 2147483647;
159 | files = (
160 | 00256F902992DB58000AD09A /* Preview Assets.xcassets in Resources */,
161 | 00256F8D2992DB58000AD09A /* Assets.xcassets in Resources */,
162 | );
163 | runOnlyForDeploymentPostprocessing = 0;
164 | };
165 | /* End PBXResourcesBuildPhase section */
166 |
167 | /* Begin PBXSourcesBuildPhase section */
168 | 00256F812992DB57000AD09A /* Sources */ = {
169 | isa = PBXSourcesBuildPhase;
170 | buildActionMask = 2147483647;
171 | files = (
172 | 00256FA629943130000AD09A /* ListView.swift in Sources */,
173 | 00256FA8299431FF000AD09A /* DetailView.swift in Sources */,
174 | 00256F9C2992DBF7000AD09A /* ViewSpec.swift in Sources */,
175 | 00256FA429943028000AD09A /* MainRouter.swift in Sources */,
176 | 00256FAA29943850000AD09A /* AlertView.swift in Sources */,
177 | 00256F8B2992DB57000AD09A /* MainView.swift in Sources */,
178 | 00256F9E2992DEC9000AD09A /* View+Modal.swift in Sources */,
179 | 00256F982992DBBA000AD09A /* Router.swift in Sources */,
180 | 00256F892992DB57000AD09A /* RouterWithNavigationStackApp.swift in Sources */,
181 | 00256F9A2992DBCF000AD09A /* RoutingView.swift in Sources */,
182 | );
183 | runOnlyForDeploymentPostprocessing = 0;
184 | };
185 | /* End PBXSourcesBuildPhase section */
186 |
187 | /* Begin XCBuildConfiguration section */
188 | 00256F912992DB58000AD09A /* Debug */ = {
189 | isa = XCBuildConfiguration;
190 | buildSettings = {
191 | ALWAYS_SEARCH_USER_PATHS = NO;
192 | CLANG_ANALYZER_NONNULL = YES;
193 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
194 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
195 | CLANG_ENABLE_MODULES = YES;
196 | CLANG_ENABLE_OBJC_ARC = YES;
197 | CLANG_ENABLE_OBJC_WEAK = YES;
198 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
199 | CLANG_WARN_BOOL_CONVERSION = YES;
200 | CLANG_WARN_COMMA = YES;
201 | CLANG_WARN_CONSTANT_CONVERSION = YES;
202 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
203 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
204 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
205 | CLANG_WARN_EMPTY_BODY = YES;
206 | CLANG_WARN_ENUM_CONVERSION = YES;
207 | CLANG_WARN_INFINITE_RECURSION = YES;
208 | CLANG_WARN_INT_CONVERSION = YES;
209 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
210 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
211 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
212 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
213 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
214 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
215 | CLANG_WARN_STRICT_PROTOTYPES = YES;
216 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
217 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
218 | CLANG_WARN_UNREACHABLE_CODE = YES;
219 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
220 | COPY_PHASE_STRIP = NO;
221 | DEBUG_INFORMATION_FORMAT = dwarf;
222 | ENABLE_STRICT_OBJC_MSGSEND = YES;
223 | ENABLE_TESTABILITY = YES;
224 | GCC_C_LANGUAGE_STANDARD = gnu11;
225 | GCC_DYNAMIC_NO_PIC = NO;
226 | GCC_NO_COMMON_BLOCKS = YES;
227 | GCC_OPTIMIZATION_LEVEL = 0;
228 | GCC_PREPROCESSOR_DEFINITIONS = (
229 | "DEBUG=1",
230 | "$(inherited)",
231 | );
232 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
233 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
234 | GCC_WARN_UNDECLARED_SELECTOR = YES;
235 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
236 | GCC_WARN_UNUSED_FUNCTION = YES;
237 | GCC_WARN_UNUSED_VARIABLE = YES;
238 | IPHONEOS_DEPLOYMENT_TARGET = 16.1;
239 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
240 | MTL_FAST_MATH = YES;
241 | ONLY_ACTIVE_ARCH = YES;
242 | SDKROOT = iphoneos;
243 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
244 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
245 | };
246 | name = Debug;
247 | };
248 | 00256F922992DB58000AD09A /* Release */ = {
249 | isa = XCBuildConfiguration;
250 | buildSettings = {
251 | ALWAYS_SEARCH_USER_PATHS = NO;
252 | CLANG_ANALYZER_NONNULL = YES;
253 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
254 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
255 | CLANG_ENABLE_MODULES = YES;
256 | CLANG_ENABLE_OBJC_ARC = YES;
257 | CLANG_ENABLE_OBJC_WEAK = YES;
258 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
259 | CLANG_WARN_BOOL_CONVERSION = YES;
260 | CLANG_WARN_COMMA = YES;
261 | CLANG_WARN_CONSTANT_CONVERSION = YES;
262 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
263 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
264 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
265 | CLANG_WARN_EMPTY_BODY = YES;
266 | CLANG_WARN_ENUM_CONVERSION = YES;
267 | CLANG_WARN_INFINITE_RECURSION = YES;
268 | CLANG_WARN_INT_CONVERSION = YES;
269 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
270 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
271 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
272 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
273 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
274 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
275 | CLANG_WARN_STRICT_PROTOTYPES = YES;
276 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
277 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
278 | CLANG_WARN_UNREACHABLE_CODE = YES;
279 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
280 | COPY_PHASE_STRIP = NO;
281 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
282 | ENABLE_NS_ASSERTIONS = NO;
283 | ENABLE_STRICT_OBJC_MSGSEND = YES;
284 | GCC_C_LANGUAGE_STANDARD = gnu11;
285 | GCC_NO_COMMON_BLOCKS = YES;
286 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
287 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
288 | GCC_WARN_UNDECLARED_SELECTOR = YES;
289 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
290 | GCC_WARN_UNUSED_FUNCTION = YES;
291 | GCC_WARN_UNUSED_VARIABLE = YES;
292 | IPHONEOS_DEPLOYMENT_TARGET = 16.1;
293 | MTL_ENABLE_DEBUG_INFO = NO;
294 | MTL_FAST_MATH = YES;
295 | SDKROOT = iphoneos;
296 | SWIFT_COMPILATION_MODE = wholemodule;
297 | SWIFT_OPTIMIZATION_LEVEL = "-O";
298 | VALIDATE_PRODUCT = YES;
299 | };
300 | name = Release;
301 | };
302 | 00256F942992DB58000AD09A /* Debug */ = {
303 | isa = XCBuildConfiguration;
304 | buildSettings = {
305 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
306 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
307 | CODE_SIGN_STYLE = Automatic;
308 | CURRENT_PROJECT_VERSION = 1;
309 | DEVELOPMENT_ASSET_PATHS = "\"RouterWithNavigationStack/Preview Content\"";
310 | DEVELOPMENT_TEAM = 8684QJA92T;
311 | ENABLE_PREVIEWS = YES;
312 | GENERATE_INFOPLIST_FILE = YES;
313 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
314 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
315 | INFOPLIST_KEY_UILaunchScreen_Generation = YES;
316 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
317 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
318 | IPHONEOS_DEPLOYMENT_TARGET = 16.0;
319 | LD_RUNPATH_SEARCH_PATHS = (
320 | "$(inherited)",
321 | "@executable_path/Frameworks",
322 | );
323 | MARKETING_VERSION = 1.0;
324 | PRODUCT_BUNDLE_IDENTIFIER = ihor.vovk.RouterWithNavigationStack;
325 | PRODUCT_NAME = "$(TARGET_NAME)";
326 | SWIFT_EMIT_LOC_STRINGS = YES;
327 | SWIFT_VERSION = 5.0;
328 | TARGETED_DEVICE_FAMILY = "1,2";
329 | };
330 | name = Debug;
331 | };
332 | 00256F952992DB58000AD09A /* Release */ = {
333 | isa = XCBuildConfiguration;
334 | buildSettings = {
335 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
336 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
337 | CODE_SIGN_STYLE = Automatic;
338 | CURRENT_PROJECT_VERSION = 1;
339 | DEVELOPMENT_ASSET_PATHS = "\"RouterWithNavigationStack/Preview Content\"";
340 | DEVELOPMENT_TEAM = 8684QJA92T;
341 | ENABLE_PREVIEWS = YES;
342 | GENERATE_INFOPLIST_FILE = YES;
343 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
344 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
345 | INFOPLIST_KEY_UILaunchScreen_Generation = YES;
346 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
347 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
348 | IPHONEOS_DEPLOYMENT_TARGET = 16.0;
349 | LD_RUNPATH_SEARCH_PATHS = (
350 | "$(inherited)",
351 | "@executable_path/Frameworks",
352 | );
353 | MARKETING_VERSION = 1.0;
354 | PRODUCT_BUNDLE_IDENTIFIER = ihor.vovk.RouterWithNavigationStack;
355 | PRODUCT_NAME = "$(TARGET_NAME)";
356 | SWIFT_EMIT_LOC_STRINGS = YES;
357 | SWIFT_VERSION = 5.0;
358 | TARGETED_DEVICE_FAMILY = "1,2";
359 | };
360 | name = Release;
361 | };
362 | /* End XCBuildConfiguration section */
363 |
364 | /* Begin XCConfigurationList section */
365 | 00256F802992DB57000AD09A /* Build configuration list for PBXProject "RouterWithNavigationStack" */ = {
366 | isa = XCConfigurationList;
367 | buildConfigurations = (
368 | 00256F912992DB58000AD09A /* Debug */,
369 | 00256F922992DB58000AD09A /* Release */,
370 | );
371 | defaultConfigurationIsVisible = 0;
372 | defaultConfigurationName = Release;
373 | };
374 | 00256F932992DB58000AD09A /* Build configuration list for PBXNativeTarget "RouterWithNavigationStack" */ = {
375 | isa = XCConfigurationList;
376 | buildConfigurations = (
377 | 00256F942992DB58000AD09A /* Debug */,
378 | 00256F952992DB58000AD09A /* Release */,
379 | );
380 | defaultConfigurationIsVisible = 0;
381 | defaultConfigurationName = Release;
382 | };
383 | /* End XCConfigurationList section */
384 | };
385 | rootObject = 00256F7D2992DB57000AD09A /* Project object */;
386 | }
387 |
--------------------------------------------------------------------------------