最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ios - Is there any advantage of using NavigationStack when working with .sheet or .fullScreenCover navigation? - Stack Overflow

programmeradmin5浏览0评论

After working with UIKit for several years I am still quite new to SwiftUI and especially to its navigation features.

Currently I am trying to get my head around NavigationStack and .navigationDestination. It seems that that using these features allows push navigation (like in UINavigationController) only. Is this correct?

When searching for ways to use NavigationStack with .sheet and/or .fullScreenCover navigation instead I find several examples which state that this is possible but has to be implemented manually:

struct ContentView: View {
    @State private var navigationPath = NavigationPath()
    @State private var presentingSheet: Bool = false
    @State private var presentingFullScreen: Bool = false
    @State private var selectedItem: String?

    var body: some View {
        NavigationStack(path: $navigationPath) {
            VStack {
                /*Button("Push to Detail") {
                    navigationPath.append("Detail")
                }*/

                Button("Present as Sheet") {
                    selectedItem = "Detail"
                    presentingSheet = true
                }

                Button("Present as FullScreen") {
                    selectedItem = "Detail"
                    presentingFullScreen = true
                }
            }
            /*.navigationDestination(for: String.self) { value in
                DetailView(value: value)
            }*/
            .sheet(isPresented: $presentingSheet) {
                if let selectedItem {
                    DetailView(value: selectedItem)
                }
            }
            .fullScreenCover(isPresented: $presentingFullScreen) {
                if let selectedItem {
                    DetailView(value: selectedItem)
                }
            }
        }
    }
}

While this obviously works, I do not understand what advantage I get from using NavigationStack in this example. NavigationPath is only utilized when using the push navigation but not when using .sheet or .fullStackCover, is it?

So, is there any reason to use NavigationStack at all, when push navigation is not used?

Is there any iOS/SwiftUI native solution when working with .sheet or .fullStackCover or to I need a custom or third party solution like the Routing Pattern?

After working with UIKit for several years I am still quite new to SwiftUI and especially to its navigation features.

Currently I am trying to get my head around NavigationStack and .navigationDestination. It seems that that using these features allows push navigation (like in UINavigationController) only. Is this correct?

When searching for ways to use NavigationStack with .sheet and/or .fullScreenCover navigation instead I find several examples which state that this is possible but has to be implemented manually:

struct ContentView: View {
    @State private var navigationPath = NavigationPath()
    @State private var presentingSheet: Bool = false
    @State private var presentingFullScreen: Bool = false
    @State private var selectedItem: String?

    var body: some View {
        NavigationStack(path: $navigationPath) {
            VStack {
                /*Button("Push to Detail") {
                    navigationPath.append("Detail")
                }*/

                Button("Present as Sheet") {
                    selectedItem = "Detail"
                    presentingSheet = true
                }

                Button("Present as FullScreen") {
                    selectedItem = "Detail"
                    presentingFullScreen = true
                }
            }
            /*.navigationDestination(for: String.self) { value in
                DetailView(value: value)
            }*/
            .sheet(isPresented: $presentingSheet) {
                if let selectedItem {
                    DetailView(value: selectedItem)
                }
            }
            .fullScreenCover(isPresented: $presentingFullScreen) {
                if let selectedItem {
                    DetailView(value: selectedItem)
                }
            }
        }
    }
}

While this obviously works, I do not understand what advantage I get from using NavigationStack in this example. NavigationPath is only utilized when using the push navigation but not when using .sheet or .fullStackCover, is it?

So, is there any reason to use NavigationStack at all, when push navigation is not used?

Is there any iOS/SwiftUI native solution when working with .sheet or .fullStackCover or to I need a custom or third party solution like the Routing Pattern?

Share Improve this question edited 11 hours ago koen 5,7297 gold badges58 silver badges101 bronze badges asked 15 hours ago Andrei HerfordAndrei Herford 18.7k24 gold badges108 silver badges254 bronze badges 2
  • 1 It seems that that using these features allows push navigation (like in UINavigationController) only. Is this correct? Yes, it is for hierarchical navigation. Both sheet and fullScreenCover are modal presentations, so it's a bit different to navigation. See the Apple documentation for an overview of intended use. That page also has a link to design guidlines, for guidance on when this approach is appropriate. – Benzy Neez Commented 15 hours ago
  • And fyi it is .sheet(item: selectedItem) – malhal Commented 13 hours ago
Add a comment  | 

2 Answers 2

Reset to default 0

In SwiftUI NavigationStack is unrelated to the sheet and fullScreenCover.

NavigationLink is like show with the controller.

If you want the global show and push or present you do need a custom setup. SwiftUI does not have a global push.

The presenting a screen functionality using sheet/fullScreenCover in SwiftUI has nothing to do with the navigation stack like in UIKit where in we require a navigation controller to either push or present the new screen.

SwiftUI Screens operates via views and not like controllers. In these cases the modifiers sheet/fullScreenCover are used to present the required view.

NavigationStack is useful when we want to operate the push functionality essentially linking a SwiftUI view to a particular destination.

If you want a global functionality I would recommend creating a boiler BaseView with fullScreenCover and have a Navigation functionality via there all handled by a ViewModel to take advantage of MVVM pattern.

  • BaseView That Wraps All Screens

      struct BaseView<Content: View>: View {
          @StateObject private var viewModel = BaseViewModel()
          let content: Content  // Child view to be wrapped
    
          var body: some View {
              content
              .fullScreenCover(item: $viewModel.activeFullScreenCover) { cover in
                  viewModel.destinationView(for: cover)
              }
              .environmentObject(viewModel)
          }
      }
    
    
  • BaseViewModel for Global Navigation

    class BaseViewModel: ObservableObject {
         @Published var activeFullScreenCover: AnyView?
    
          func presentFullScreenCover<Content: View>(_ view: Content) {
              activeFullScreenCover = AnyView(view)
          }
    
          func dismissFullScreenCover() {
              activeFullScreenCover = nil
          }
      }
    
  • Make Sure to wrap the views inside Base view

    @main
    struct MyApp: App {
        var body: some Scene {
            WindowGroup {
                BaseView(content: HomeView()) // HomeView is now inside BaseView
            }
        }
    }
    
  • Child Views Can Trigger Full-Screen Presentation

    struct HomeView: View {
        @EnvironmentObject var viewModel: BaseViewModel
    
        var body: some View {
            VStack {
                Button("Show Full-Screen Modal") {
                    viewModel.presentFullScreenCover(ChildView())
                }
            }
            .navigationTitle("Home")
        }
    }
    

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论