Search code examples
iosswiftswiftuiapple-watchwatchos

Why doesn't EmptyView() work on WatchOS with SwiftUI?


NavigationView() doesn't work on WatchOS under swiftUI but I found a neat trick(?) here to get the NavigationView working on WatchOS. Adding this allows one to use NavigationView() in watchOS projects

#if os(watchOS)
struct NavigationView<Content: View>: View {
    let content: () -> Content

    init(@ViewBuilder content: @escaping () -> Content) {
        self.content = content
    }

    var body: some View {
        VStack(spacing: 0) {
            content()
        }
    }
}
#endif

The problem is, a method I want to use to pop a new view from a function (like a button) requires a NavigationLink which shows an EmptyView(), and while that works on iOS it doesn't work on WatchOS.

Working code on iOS:

import SwiftUI

struct ContentView: View {
    
    @State var showNewView = false
    
    var body: some View {
        NavigationView{
            VStack {
            NavigationLink(destination: Text("This text view"), isActive: self.$showNewView) {EmptyView()}
            
                Button("Not the world!") {
                    self.showNewView = true
                }
            Text("Hello, World!")
            }
        }
    }
}

If you put that code in to a new WatchOS application, and include the relevant code snippet to make NavigationView work on WatchOS, it allows the application to be made, but the button to change Views won't do anything.

It will change the variable showNewView to true (I've tested by having a print statement) but that becoming true won't show the new view.

If I put a non-emptyview (Something like Text("Merry Christmas")) in there, it will work.

I'm currently looking for another solution to my problem of getting a new view to show in SwiftUI through a function (not through making some sort of list with NavigationView), but I am curious about what is going on. I assume it has something to do with hack used to get NavigationView working on WatchOS, but I don't really know how that code snippet is workin.


Solution

  • Here is a solution - just put navigation link into background.

    Tested with Xcode 11.4

    VStack {
        Button("Not the world!") {
            self.showNewView = true
        }
        .background(NavigationLink(destination: Text("This text view"), 
             isActive: self.$showNewView) {EmptyView()} )
    
        Text("Hello, World!")
    }