I have the following ViewModifier
and it does not work:
import SwiftUI
struct NavLink: ViewModifier {
let title: String
func body(content: Content) -> some View {
NavigationLink(destination: content) {
Text(title)
}
}
}
extension View {
func navLink(title: String) -> some View {
modifier(NavLink(title: title))
}
}
If I use that as follows:
import SwiftUI
struct MainScreen: View {
var body: some View {
NavigationStack() {
VStack {
// This does not work
NavStackScreen()
.navLink(title: "Nav Stack")
// But this does
Helper.linked(to: NavStackScreen(), title: "Nav Stack 2")
}
}
}
}
struct Helper {
static func linked(to destination: some View, title: String) -> some View {
NavigationLink(destination: destination) {
Text(title)
}
}
}
It creates the link and pushes a new view onto the screen if tapped; however, the contents of the NavStackScreen are not displayed, only an empty screen. Any ideas about what is going on?
Contents of NavStackScreen for reference:
struct NavStackScreen: View {
var body: some View {
Text("Nav Stack Screen")
.font(.title)
.navigationTitle("Navigation Stack")
}
}
If I use a static helper function within a helper struct, then it works correctly:
static func linked(to destination: some View, title: String) -> some View {
NavigationLink(destination: destination) {
Text(title)
}
}
I added the full code of the MainView for reference and updated the example with more detail for easy reproduction.
The modifier doesn't work because the content
argument is not the actual view being modified, but instead is a proxy:
content is a proxy for the view that will have the modifier represented by Self applied to it.
This is what a quick debugging over the modifier shows:
(lldb) po content
SwiftUI._ViewModifier_Content<SwiftUIApp.NavLink>()
As the proxy is an internal type of SwiftUI, we can't know for sure why NavigationLink
doesn't work with it.
A workaround would be to skip the modifier, and only add the extension over View
:
extension View {
func navLink(title: String) -> some View {
NavigationLink(destination: content) {
Text(title)
}
}
}