SwiftUI - menu not appearing and double toolbar for NavigationView - swift

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.

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.

navigation title custom

I am trying to add a custom navigation title to my SwiftUI project. I have a few tabs and I’m getting a weird bug. For every tab I am getting the same navigation title of "Home" and I can’t seem to change it or remove it. I’m not sure why there is even a title for each tab as I never added one. I have tried using .navigationTitle("my title") to edit the tab title. This is not working though, anyone know a fix? I will attach some code below.
TabView(){
FeedView()
.navigationTitle("hustles")
.tabItem {
Image(systemName: "h.circle")
}
JobsView()
.tabItem {
Image(systemName: "j.circle")
}
}
var body: some View {
VStack(alignment: .leading){
tweetsView
Spacer()
}
.navigationTitle("Profile")
}
just add navigation view inside each tab item and then add it the specific view inside the navigation view

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: Creating a Pull-down menu

in the HIG Apple writes: In iOS 14 and later, a button can display a pull-down menu that lists items or actions from which people can choose
This is exactly what I want for my project. This picture where they have a "more" bar button with a drop-down menu fits the bill perfectly. Does anyone have an example, though, of how to create a pull-down menu (not context-menu) from a button with SwiftUI?
You can simply use the Menu view that is new for iOS in iOS 14.
It acts as a button and when pressed presents the context menu. You can use a Label if you want an image and even nest different views, as shown in the
example in the documentation.
struct ContentView: View {
#State var text = "Hello World"
var body: some View {
NavigationView {
Text("Hello World")
.navigationTitle("Hello")
.navigationBarItems(trailing: {
Menu {
Button(action: { text = "Hello there" }) {
Label("Hello", systemImage: "pencil")
}
} label: {
Image(systemName: "ellipsis.circle")
}
}())
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
Instead of navigationBarItems one should probably use toolbar, however I found that to be quite unreliable starting with Beta 4.

SwiftUI - Apple Watch Menu (Force Touch)

I'm trying to implement a menu on Apple Watch using SwiftUI but I can't find a way to do it. Even on the interface.storyboard, I can't drag/drop the menu.
Did you manage to make it work with SwiftUI? If yes, how?
I searched online but nothing so far.
Yes, this is possible. It's important to remember that unlike on iOS, a view can have only one single context menu, individual elements within the view can not have their own context menu.
Anyway, to implement a context menu (force touch menu) on Apple Watch with SwiftUI, add the .contextMenu() modifier to top-most view in your body
Example:
var body: some View {
Group {
Text("Hello Daymo")
}
.contextMenu(menuItems: {
Button(action: {
print("Refresh")
}, label: {
VStack{
Image(systemName: "arrow.clockwise")
.font(.title)
Text("Refresh view")
}
})
})
}
Edit the button (or add buttons) as you see fit.