Using NavigationLink in ForEach loop in SwiftUI - swift

I have a view that has a grid of buttons. These buttons lead to another view, but depending on which button is pressed, passes in different information that will populate the view. This is all already in a NavigationView.
ForEach(userData) { user in
NavigationLink(destination: DestinationView(userData: user.data)) {
Button(action: {}) {
//button styling
}
}
}
The buttons display as intended and are clickable but nothing happens. The subview is a giant black rectangle for testing and it does not appear. I tried adding to each NavigationLink the isDetailLink(false) modifier, but that did not do anything.

Related

The EditButton for NavigationView is not working properly for iPad ( But correct for iPhone)

I am new in SwiftUI developing, In a SwiftUI project, I created a list of items then I followed the tips in this link to enabled edit button for this,
https://developer.apple.com/documentation/swiftui/editbutton
It works properly for iPhone interface, But in iPad, It has a very strange behaviour. Look at this video below to see how it works in iPad.
https://imgur.com/a/0CLkqiz
If you check this, the way it shows in iPad, when the Edit button text wants to turn to Done, the text steps forward and also creates a transparency with done and edit while it works properly and smooth and fixed in iPhone. I wonder if there might be any special settings for iPad interface in SwiftUI that would fix this problem.
This is my code for this:
struct QRCreator: View {
#State var showingCreateView = false
#State public var fruits = [
"Apple",
"Banana",
"Papaya",
"Mango"
]
var body: some View {
NavigationView {
List {
ForEach(fruits, id: \.self) { fruit in
Text(fruit)
}
.onDelete { fruits.remove(atOffsets: $0) }
.onMove { fruits.move(fromOffsets: $0, toOffset: $1) }
}
.navigationTitle("Fruits2")
.navigationBarItems(trailing:
Button(action: {
showingCreateView = true
}){
Image(systemName: "plus.viewfinder")
.font(.largeTitle)
}
)
.toolbar {
EditButton()
}
}
}
and here is ContentView which I define three tabs in it like this
TabView
{
NavigationView{
QRScanner()
}
.tabItem
{
Image(systemName: "qrcode.viewfinder")
Text("Scanner")
}
NavigationView {
QRCreator()
}
.tabItem
{
Image(systemName: "doc.fill.badge.plus")
Text("Creator")
}
NavigationView
{
QRSetting()
}
.tabItem
{
Image(systemName: "gear")
Text("Setting")
}
}
There seem to be two layers at play:
From the screen recording, it would appear that your NavigationView is actually wrapped by another NavigationView (or NavigationStack/SplitView) somewhere further up the view hierarchy in your implementation. Besides the odd layout, this also creates a tricky situation in regards to toolbar items like your buttons, and the EditMode environment value that EditButton manipulates.
There is an iPad-specific animation bug in SwiftUI's implementation of EditButton. When clicked with a mouse/trackpad as in your screen recording, the button briefly shows both labels ("Edit" & "Done") at the same time. This doesn't happen when you tap the button directly.
It is only when issues 1 & 2 collide, that I actually run into the more problematic behavior that you've captured: the button jumps and the list also jumps.
If I keep everything as you have shown it (including the doubled-up NavigationViews), but tap the button instead of clicking it with a cursor, things seem fine (although I would expect other possible issues down the road).
If I get rid of the outer NavigationView, but click the button, the button itself still exhibits a slightly odd animation, but it is nowhere near as bad as before. And most importantly, the list animates and behaves correctly.
I tried a couple of approaches to work around the button's remaining animation bug, but nothing short of re-implementing a custom edit button worked.
PS: I know you might've already come across this, but since you said that you're just starting out with iOS 16 introduced new views and APIs for navigation (and in typical fashion for SwiftUI's documentation, older pages like the one for EditButton have not been updated). Depending on how complex your app is, switching later on can be a bit of a pain, so here's a good WWDC video introducing the new API: The SwiftUI cookbook for navigation as well as some blog posts.

Button remains tappable after removing from view hierarchy - SwiftUI

I'm trying to show and hide a view based on a certain state. But even after that view is removed from the hierarchy, it still remains tappable for a few moments, leading to phantom button presses. This is occurring only in iOS 16 to my knowledge.
Note that this only occurs when using the .zIndex modifier, which I need in order to transition the view out smoothly. The bug occurs with or without a transition modifier, however.
Minimum working example (tap the show button, then tap the hide button multiple times. If it worked correctly, the hide button handler should only trigger once, since it is removed from the hierarchy. In reality it can be triggered many times)
struct ContentView: View {
#State var show = false
var body: some View {
ZStack {
Button {
print("show")
show = true
} label: {
Text("show")
.foregroundColor(.white)
.padding()
.background(Color.blue.cornerRadius(8))
}
if show {
Button {
// this can be triggered multiple times if you tap fast
print("hide")
show = false
} label: {
Text("hide")
.foregroundColor(.white)
.padding(64)
.background(Color.red.cornerRadius(8))
}
.zIndex(1) // if we remove the zindex, it won't happen. but then we lose the ability to transition this view out.
}
}
}
}
Has anyone else experience this bug? I don't know a workaround besides removing zIndex, is there a way to fix it without losing transitions?
I filed a feedback for this FB11753719

SwiftUI - menu not appearing and double toolbar for NavigationView

I am creating a iOS app with XCode. All source code has been written and compiled.
The app runs in the iOS simulator.
The user interface was created in SwiftUI and it appears as expected.
The navigation seems to be working across the screens but I cannot have the menu as designed and I see a double toolbar where the back button appears.
The navigation happens by NavigationLinks associated to buttons.
If I navigate one screen deep I have a back button and a back icon. It seems that the back button is a menu in fact.
If I navigate two screens deep the back button shows a menu with two back options, one lets the user navigate back one level, the other lets the user navigate back two levels.
The main problem is that in the main screen no menu appears.
It doesn't depend on the content of the main view. Indeed if it is stripped down from the View still I do not have the menu, but I do not have the double toolbar either.
var body: some View {
NavigationView {
VStack{
Text("HELLO")
/*here was a sort of master-detail layout*/
}
}.navigationViewStyle(StackNavigationViewStyle()).navigationTitle("SwiftUI").toolbar {
ToolbarItem(placement: .primaryAction) {
Menu
{ //this is what the menu content is like but it never appeared
NavigationLink(destination:HelpView())
{ Label(help_menu_item, systemImage: "")
}
Button(action: {}) {
Label(liability_disclaimer_menu_item, systemImage: "")
}
Button(action: {}) {
Label(about_menu_item, systemImage: "")
}
//other buttons
}//menu
label: {
Label("Menu", systemImage: "ellipsis")
}
}
}
} //body
What changes or checks can be done? I want the menu and a single toolbar.
I also tried commenting things and trying step by step additions but even the simplest case does not work.
Put the toolbar modifier on the top-level view within the NavigationView, not on the NavigationView itself.

SwiftUI - How to get a transparent status bar when in a tabbed view?

My app first root view is a tabbed view with two tabs. The second tab is a navigation view with a form. The setting can be summarised like this:
struct ContentView: View {
var body: some View {
TabView {
// First view
// ...
NavigationView {
Form {
// Form details
// ...
}
}
.tabItem {
// Text and image for the tab view item
}
}
}
}
Problem is that the form view's background is not white, it is slightly contrasted (as for grouped lists) and this creates a disgraceful separation with the status bar at the top:
This behaviour is not present in other app such as Apple ones. For instance the main view of Pages app is a tab view and the status bar remains transparent and of the same colour as the top bar title.
I'd like the same behaviour as the iPhone settings app, with a header colour matching the status bar view.
The problem here seems to be the tab view that takes control of the status bar appearance, if I remove it all goes normal.
Is there a way to get this behaviour inside a tab view?
You can wrap your TabView in a ZStack and set .edgesIgnoringSafeArea(.top) for your stack
var body: some View {
ZStack {
TabView {
Form {
Text("OK")
}
}.tabItem {
Text("Show")
}
}.edgesIgnoringSafeArea(.top)
}

SwiftUI - NavigationView Adds Detail Indicator ">" to List View - How to remove?

When using a NavigationView to link to a Detail View from a List, SwiftUI automatically adds a > detail/disclosure indicator to the right side of the List view row. The > and the padding around it are causing issues with my layout which I would like to extend all the way to the end of the row. How can I remove the disclosure indicator?
The same question was asked here SwiftUI NavigationButton without the disclosure indicator? but at the time, there was no solution, only work arounds that don't work so well.
Is there a solution to this problem yet, or is it a matter of waiting for SwiftUI to be updated?
Screenshot of the Issue:
iOS13 , iOS 14
List {
ForEach(items) { item in
ZStack {
CustomView(item: item)
NavigationLink(destination: anotherView()) {
EmptyView()
}
.opacity(0)
.buttonStyle(PlainButtonStyle())
}
}
}