SwiftUI - NavigationLink not working when clicked - swiftui

Currently using:
Xcode 11 Beta 5
Mac OSX Catalina Beta 5
Here is the code:
import SwiftUI
struct SwiftUIView : View {
var body: some View {
NavigationView {
NavigationLink(destination: Product()) {
Text("Click")
}
.navigationBarTitle(Text("Navigation"))
}
}
}
#if DEBUG
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
SwiftUIView()
}
}
#endif
And here is result:
When tapped or clicked on button, it should go to detail view, bit nothing is happening.
Notes:
The Landmark example project by apple, is also not working when tapped on the landmarks on home screen.
This website mentions that "Not sure if it is a bug or by design, in Beta 5 above code won't work"
https://fuckingswiftui.com/#navigationlink

It must be a bug. But as a workaround, when on the top view of a NavigationView, embed NavigationLink inside a VStack. The button will gain its proper style and "clickability".
struct SwiftUIView : View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: Product()) {
Text("Click")
}
}.navigationBarTitle(Text("Navigation"))
}
}
}

Works in Xcode(11.2)
struct MasterView: View {
#State var selection: Int? = nil
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: DetailsView(), tag: 1, selection: $selection) {
Button("Press") {
self.selection = 1
}
}
}
}
}

Related

SwiftUI: NavigationLink pops out immediately on WatchOS 8.1RC in Tabview

I have discovered a regression in watchOS 8.1RC with NavigationLink triggered from a TabView.
It's immediately dismissed.
It was working in watchOS 8.0 or in Simulator (watchOS 8.0).
Do you know a workaround ?
Thanks
Sample code:
import SwiftUI
#main
struct TestNavigationApp: App {
var body: some Scene {
WindowGroup {
NavigationView {
ContentView()
}
}
}
}
struct ContentView: View {
var body: some View {
List {
NavigationLink(destination: ContentView1()) {
Text("To TabView")
}
}
}
}
struct ContentView1: View {
var body: some View {
TabView {
NavigationView {
NavigationLink(destination: ContentView2()) {
Text("To ContentView2")
}
}
VStack {
Text("Screen2")
}
}
}
}
struct ContentView2: View {
var body: some View {
Text("ContentView2")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
I'm experiencing the same issue with watchOS 8.1 (and 8.3 beta) while it was working with previous watchOS versions.
We were able to get it working again by moving the NavigationView inside the TabView. This workaround isn't ideal at all but it does seem to work.
#State private var tabSelection = 1
var body: some Scene {
WindowGroup {
TabView(selection: $tabSelection) {
NavigationView {
// List goes here
}
.tag(1)
VStack(alignment: .center, spacing: 12, content: {
// content 2nd tab: we didn't have a list in the 2nd tab
})
.tag(2)
}
}
}
However, there are 2 things impacted with this fix:
I didn't get the navigationBarTitle working, so there won't be a title on top of the screen.
If you click on an item in the list, it will navigate to your page (as expected) but the TabView dots at the bottom of the screen will remain.

How can I Hide TabBar in specific Views, in iOS 15 using SwiftUI

I need my TabBar to disappear if I click on a NavigationLink.
I know you can achieve that in iOS 14 with the following code:
NavigationView{
TabView{
View1().tabItem {
Image(systemName: "house.fill")
Text("Home")
}
}
}
And View1:
struct View1: some View {
var body: some View {
NavigationView{
NavigationLink(destination: Text("New Page without the Tabbar")) {
Text("Link")
}
}
}
}
But somehow this don't works in iOS 15...
Are there any other workarounds?
You could try using only one NavigationView, like in this example:
import SwiftUI
#main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
TabView {
View1().tabItem {
Image(systemName: "house.fill")
Text("Home")
}
}
}
}
}
struct View1: View {
var body: some View {
// ---> here no NavigationView
NavigationLink(destination: Text("New Page without the Tabbar")) {
Text("Link")
}
}
}

Creating nav link error in Swift UI/ Xcode

I am trying to add a Navigation view that goes from my ContentView to my list items inside of my SectionView and then goes to my DetailView...i'm getting an error and i'm not sure why? im trying to nav link SelectionView( codeName: "Y")
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
List {
NavigationLink("Y", destination:codeName.
(model: .codeName))
List (models) { model in
SelectionView(codeName: model.codeName)
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.previewLayout(.device)
.preferredColorScheme(.dark)
.previewDevice("iPhone 13 Pro Max")
}
}
#endif
}
}
The destination also should be a view.
struct ContentView: View {
var body: some View {
NavigationView {
List {
ForEach(0 ..< 5) { item in
NavigationLink(
destination: Text("Destination \(item)"),
label: {
Text("Hello, world! \(item)")
.padding()
})
}
}
}
}
}

SwiftUI Navigation Controller stuttering with two Navigationlinks per List row

I am trying to create two NavigationLinks in a repeating List. Each has a separate destination. The code all works fine until I imbed the call to the root view in a List/ForEach loop. At which point the navigation becomes very strange.
Try to click on either link and then click the back indicator at the top. It will go to one NavigationLink, and then the other. Sometimes in a different order, and sometimes it will auto-return from one of the links, and othertimes it won't open the second detail view until you return from the first detail view. It does this both in Preview, as well as if you build and run the application.
I have distilled down the code to the most basic below. If you comment the 2 lines as indicated in ContentView, you will then see correct behavior.
I am running Catalina 10.15.5, xCode 11.6, with the application target of IOS 13.6.
How can I modify the code, so that it will work with the List/ForEach loop?
import SwiftUI
struct DetailView1: View {
var body: some View {
HStack {
Text("Here is Detail View 1." )}
.foregroundColor(.green)
}
}
struct DetailView2: View {
var body: some View {
HStack {
Text( "Here is Detail View 2.") }
.foregroundColor(.red)
}
}
struct RootView: View {
var body: some View {
HStack {
VStack {
NavigationLink(destination: DetailView1())
{ VStack { Image(systemName: "ant.circle").resizable()
.frame(width:75, height:75)
.scaledToFit()
}.buttonStyle(PlainButtonStyle())
Text("Tap for Detail 1.")
.foregroundColor(.green)
}
}
NavigationLink(destination: DetailView2())
{ Text("Tap for Detail 2.")
.foregroundColor(.red)
}
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
// Comment the following line for correct behavior
List { ForEach(0..<3) {_ in
RootView()
// Comment the following line for correct behavior
} }
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
ContentView()
.navigationBarTitle("Strange Behavior")
}
}
}
In your case both navigation links are activated at once user tap a row, to avoid this below is possible approach
Tested with Xcode 12 / iOS 14
The idea is to have one link which is activated programmatically and destination is selected dynamically depending on which button is clicked
struct RootView: View {
#State private var isFirst = false
#State private var isActive = false
var body: some View {
HStack {
VStack {
Button(action: {
self.isFirst = true
self.isActive = true
})
{ VStack { Image(systemName: "ant.circle").resizable()
.frame(width:75, height:75)
.scaledToFit()
}
Text("Tap for Detail 1.")
.foregroundColor(.green)
}
}
Button(action: {
self.isFirst = false
self.isActive = true
})
{ Text("Tap for Detail 2.")
.foregroundColor(.red)
}
.background(
NavigationLink(destination: self.destination(), isActive: $isActive) { EmptyView() }
)
}
.buttonStyle(PlainButtonStyle())
}
#ViewBuilder
private func destination() -> some View {
if isFirst {
DetailView1()
} else {
DetailView2()
}
}
}

How to disable NavigationView push and pop animations

Given this simple NavigationView:
struct ContentView : View {
var body: some View {
NavigationView {
VStack {
NavigationLink("Push Me", destination: Text("PUSHED VIEW"))
}
}
}
}
Did anyone find a way of disabling the NavigationView animation when a destination view is pushed/popped into/from the stack?
This has been possible in UIKit since iOS2.0! I think it is not too much to ask from the framework. I tried all sorts of modifiers on all views (i.e., the NavigationView container, the destination view, the NavigationLink, etc)
These are some of the modifiers I tried:
.animation(nil)
.transition(.identity)
.transaction { t in t.disablesAnimations = true }
.transaction { t in t.animation = nil }
None made a difference. I did not find anything useful in the EnvironmentValues either :-(
Am I missing something very obvious, or is the functionality just not there yet?
Xcode 11.3:
Right now there is no modifier to disable NavigationView animations.
You can use your struct init() to disable animations, as below:
struct ContentView : View {
init(){
UINavigationBar.setAnimationsEnabled(false)
}
var body: some View {
NavigationView {
VStack {
NavigationLink("Push Me", destination: Text("PUSHED VIEW"))
}
}
}
}
First you need state for the NavigationLink to respond to, then set that state inside a transaction with animations disabled, as follows:
struct ContentView : View {
#State var isActive = false
var body: some View {
NavigationView {
VStack {
NavigationLink(isActive: $isActive, destination: {
Text("PUSHED VIEW")}) {
Text("Push Me")
}
Button("Navigate Without Animation") {
var transaction = Transaction()
transaction.disablesAnimations = true
withTransaction(transaction) {
isActive = true
}
}
}
}
}
}
I recently created an open source project called swiftui-navigation-stack (https://github.com/biobeats/swiftui-navigation-stack) that contains the NavigationStackView, a view that mimics the navigation behaviours of the standard NavigationView adding some useful features. For example, you could use the NavigationStackView and disable the transition animations as requested by Kontiki in the question. When you create the NavigationStackView just specify .none as transitionType:
struct ContentView : View {
var body: some View {
NavigationStackView(transitionType: .none) {
ZStack {
Color.yellow.edgesIgnoringSafeArea(.all)
PushView(destination: View2()) {
Text("PUSH")
}
}
}
}
}
struct View2: View {
var body: some View {
ZStack {
Color.green.edgesIgnoringSafeArea(.all)
PopView {
Text("POP")
}
}
}
}
PushView and PopView are two views that allow you push and pop views (similar to the SwiftUI NavigationLink). Here is the complete example:
import SwiftUI
import NavigationStack
struct ContentView : View {
var body: some View {
NavigationStackView(transitionType: .none) {
ZStack {
Color.yellow.edgesIgnoringSafeArea(.all)
PushView(destination: View2()) {
Text("PUSH")
}
}
}
}
}
struct View2: View {
var body: some View {
ZStack {
Color.green.edgesIgnoringSafeArea(.all)
PopView {
Text("POP")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
The result is:
It would be great if you guys joined me in improving this open source project.