NavigationLink Issue on Device

When running app on iPhone Xs simulator all works & looks great. When running on SAME Device, the NavigationLinks are being displayed? Issue is NOT present on IPad Device however (i.e., all looks & works fine)? 

Issue submitted to Apple with no response as of this writing.

PLATFORM AND VERSION  iOS  macOS Monterey 12.0.1 XCODE 13.1 BOTH devices (iPhone & iPad) are operating with iOS 15.1 Screenshots & code are below.

STEPS TO REPRODUCE  Confirmed NavigationLinks (2 of them) were being displayed on Device by commenting out & they do not show, but of course there is no real link then.

Also tried embedding in VStack & HStack & they BOTH appeared in their respective configurations (i.e., On top of each other in VStack and side-by-side with HStack). 

import SwiftUI
import Combine

struct PrimaryView: View {
  @EnvironmentObject var gameView: GameViewController
  @State private var selection: String? = nil
  @State private var showSettingsAlert = false
  @State private var showInfoAlert = false
   
  init() {
    UINavigationBar.appearance().backgroundColor = .clear
    UISegmentedControl.appearance().selectedSegmentTintColor = .blue
    UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
    UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.blue], for: .normal)
  }
   
  var body: some View {
    NavigationView {
      VStack{
        GameUIView()
        NavigationLink(destination: SettingsView(), tag: "Settings", selection: $selection) { EmptyView() }
        NavigationLink(destination: AppInfoView(), tag: "Info", selection: $selection) { EmptyView() }
        HStack{
          Button( action: {
            self.selection = "Settings"
            if gameView.gameStarted && !gameView.gamePaused {
              self.showSettingsAlert = true
            }
          }) {
            Text("Game Settings")
            Image(systemName: (showSettingsAlert ? "gearshape.fill" : "gearshape"))
          }
          .alert(isPresented: $showSettingsAlert) {
            Alert(title: Text("Cannot View or Change Settings!"), message: Text("Game is Running or Game is NOT Paused!! Must not be running or else in Pause State to view Game Settings!"), dismissButton: .default(Text("Got it!")))
          }
          Spacer()
          Button( action: {
            self.selection = "Info"
            if gameView.gameStarted && !gameView.gamePaused {
              self.showInfoAlert = true
            }
          }) {
            Text("Game Info")
            Image(systemName: (showInfoAlert ? "questionmark.diamond.fill" : "questionmark.diamond"))
           }
          .alert(isPresented: $showInfoAlert) {
            Alert(title: Text("Cannot View Application Info!"), message: Text("Game is Running or Game is NOT Paused!! Must not be running or else in Pause State to view Game Information!"), dismissButton: .default(Text("Got it!")))
          }
          .navigationBarHidden(true)
          .navigationBarTitle("Back To Game", displayMode: .inline)
        }
      }
    }
    .navigationViewStyle(StackNavigationViewStyle())
    .alert(isPresented: $gameView.gameEnded, content: {
      Alert(title: Text("Game Has Ended"), message: Text("To play game again you MUST close app and restart!"), dismissButton: .default(Text("Got it!")))
    })
  }
}

What happens if you replace EmptyView() with Text("") for instance ?

Do you then get the same result on iPhone and on simulator ?

An interesting behavior. When I tested your code on my iPhone 7 Plus (iOS 14.8.1), the links were not shown.


Also tried embedding in VStack & HStack

I usually use ZStack when I want some hidden NavigationLinks.

        NavigationView {
            ZStack {
                NavigationLink(destination: SettingsView(), tag: "Settings", selection: $selection) { EmptyView() }
                NavigationLink(destination: AppInfoView(), tag: "Info", selection: $selection) { EmptyView() }
                VStack{
                    GameUIView()
                    HStack{
                        //...
                    }
                }
            }
        }
        .navigationViewStyle(StackNavigationViewStyle())
        //...

Here you go.

sending again since the previous entry was poor. Here is code that replicates issue without frills o iPhone Xs with iOS 15.1


//
// AppInfoView.swift
// TestApp
//

import SwiftUI

struct AppInfoView: View {
   var body: some View {
       Text("Application Info")
   }
}

//
// ContentView.swift
// TestApp
//

import SwiftUI

struct ContentView: View {
   @EnvironmentObject var gameView: GameViewController
   @State private var selection: String? = nil
   @State private var showSettingsAlert = false
   @State private var showInfoAlert = false
   
   init() {
       UINavigationBar.appearance().backgroundColor = .clear
   }
   
   var body: some View {
       NavigationView {
           //           ZStack{
           //               NavigationLink(destination: SettingsView(), tag: "Settings", selection: $selection) { EmptyView() }
           //               NavigationLink(destination: AppInfoView(), tag: "Info", selection: $selection) { EmptyView() }
           VStack{
               GameUIView()
               ZStack{
                   NavigationLink(destination: SettingsView(), tag: "Settings", selection: $selection) { EmptyView() }
                   NavigationLink(destination: AppInfoView(), tag: "Info", selection: $selection) { EmptyView() }
                   HStack{
                       Button( action: {
                           self.selection = "Settings"
                           if gameView.gameStarted && !gameView.gamePaused {
                               self.showSettingsAlert = true
                           }
                       }) {
                           Text("Game Settings")
                               .font(.system(size: (CGFloat(16)), weight: .bold, design: .serif))
                               .foregroundColor(.blue)
                           Image(systemName: (showSettingsAlert ? "gearshape.fill" : "gearshape"))
                               .font(.system(size: (CGFloat(16)), weight: .bold, design: .serif))
                       }
                       .alert(isPresented: $showSettingsAlert) {
                           Alert(title: Text("Cannot View or Change Settings!"), message: Text("Game is Running or Game is NOT Paused!! Must not be running or else in Pause State to view Game Settings!"), dismissButton: .default(Text("Got it!")))
                       }
                       Spacer()
                       Button( action: {
                           self.selection = "Info"
                           if gameView.gameStarted && !gameView.gamePaused {
                               self.showInfoAlert = true
                           }
                       }) {
                           Text("Game Info")
                               .font(.system(size: (CGFloat(16)), weight: .bold, design: .serif))
                               .foregroundColor(.blue)
                           Image(systemName: (showInfoAlert ? "questionmark.diamond.fill" : "questionmark.diamond"))
                               .font(.system(size: (CGFloat(16)), weight: .bold, design: .serif))
                       }
                       .alert(isPresented: $showInfoAlert) {
                           Alert(title: Text("Cannot View Application Info!"), message: Text("Game is Running or Game is NOT Paused!! Must not be running or else in Pause State to view Game Information!"), dismissButton: .default(Text("Got it!")))
                       }
                       .navigationBarHidden(true)
                       .navigationBarTitle("Back To Game", displayMode: .inline)
                   }
               }
           }
           
           //           }
           .navigationViewStyle(StackNavigationViewStyle())
           .alert(isPresented: $gameView.gameEnded, content: {
               Alert(title: Text("Game Has Ended"), message: Text("To play game again you MUST close app and restart!"), dismissButton: .default(Text("Got it!")))
           })
       }
   }
}

//
// GameUIView.swift
// TestApp
//

import SwiftUI

struct GameUIView: View {
   var body: some View {
       Spacer()
       Text("Game View Area")
       Spacer()
   }
}

//
// GameViewController.swift
// TestApp
//

import Foundation
import UIKit

class GameViewController: UIViewController, ObservableObject {
   @Published var gameStarted = Bool(false)
   @Published var gamePaused = Bool(false)
   @Published var gameEnded = Bool(false)
   
}

//
// SettingsView.swift
// TestApp
//

import SwiftUI

struct SettingsView: View {
   var body: some View {
       Text("Settings")
   }
}

Thanks for updating the code. Unfortunately, I do not have a device Xs/iOS 15.1 .

Tested on iPhone 12 Pro Max/iOS 15.1

Exactly the same as the updated code:

ZStack enabled as I have suggested:

And the latter is what I intend and is not same as first image (left).

As there is no guarantee that NavigationLink with EmptyView would be shown as actually empty or not, so, I usually make them under the hood using ZStack. (In my usual apps, the hood covers whole area without transparent areas.)

NavigationLink Issue on Device
 
 
Q