Reputation: 5076
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.
Upvotes: 2
Views: 662
Reputation: 32785
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)
}
}
}
Upvotes: 1