Home > database >  SwiftUI - Can't able to present fullscreen with Navigation Link in iOS 16
SwiftUI - Can't able to present fullscreen with Navigation Link in iOS 16

Time:01-06

I'm trying to navigate and/or present fullscreen using the NavigationLink and it will vary based on the condition. When I'm trying to do that, I'm getting the compilation error as Type '() -> ()' cannot conform to 'View'. Is there any way I can achieve this?

Note: I tried to hide the NavigationBar for my ErrorView. so that I can able to just see the content. Since I'm doing this from HostingViewController, I can able to see the HostingViewController navigation bar for my ErrorView as well. That's the reason why I trying the .fullScreenCover approach.

import SwiftUI

struct LoginView: View {
    @State private var isSelected: Bool = false
    @State private var isSuccess: Bool = false

    var nextButton: some View {
        HStack {
                NavigationLink("Test") {
                 if isSuccess {
                    HomeView(user: user)
                  } else {
                    isSelected.toggle()
                  }
                }
            .fullScreenCover(isPresented: $isSelected) {
                 ErrorView()
               }
            .buttonStyle(PlainButtonStyle())
            .font(.system(size: 24))
        }
    }

    var body: some View {
        NavigationStack {
            nextButton
        }
    }

}

CodePudding user response:

This will rid the error message.

   struct LoginView: View {
        @State var isSuccess: Bool = false
            
    var body: some View {
        NavigationStack {
            NavigationLink {
                HomeView()
            } label: {
                Text("Login")
            }
            .fullScreenCover(isPresented: .constant(!isSuccess), content: {
                    ErrorView()
            })
            .buttonStyle(PlainButtonStyle())
            .font(.system(size: 24))
        }
    }
}

CodePudding user response:

The problem is that isSelected.toggle() is not a view and thus cannot be used in the destination argument. You shouldn't try to execute code that mutates variables in view building functions.

Also, when you click on a NavigationLink, its destination will be presented. Since the old isActive NavigationLink is deprecated, I don't think you can prevent the presentation of the destination. Maybe by pushing a nil value but I haven't tried that.

So my proposed solution uses a button instead of a NavigationLink. If isSuccess it can navigate to your desired view else it pops up the error full screen cover.

But using a path in a NavigationStack can get pretty complicated imo.

struct LoginView: View {
    struct UserInfo: Hashable {
        var name: String
        var email: String
    }
    
    enum Path: Hashable {
        case user(UserInfo)
    }
    
    @State private var isSelected: Bool = false
    @State private var isSuccess: Bool = true
    
    @State var path: [Path] = []
    
    var nextButton: some View {
        HStack {
            Button {
                if isSuccess {
                    path.append(Path.user(UserInfo(name: "Subbu", email: "")))
                } else {
                    isSelected = true
                }
            } label: {
                Text("Test")
            }
            .buttonStyle(.plain)
            .font(.system(size: 24))
        }
        .fullScreenCover(isPresented: $isSelected) {
            Text("ErrorView")
        }
    }
    
    var body: some View {
        NavigationStack(path: $path) {
            nextButton
                .navigationDestination(for: Path.self) { pathItem in
                    switch(pathItem) {
                    case .user(let userInfo):
                        Text("\(userInfo.name)")
                    }
                }
        }
    }
}
  • Related