Navigation bar is hidden but not allowing header button click in SwiftUI - xcode

I am trying to hide the navigation bar in SwiftUI, able to hide the navigation bar but it disables user-interaction of my header button.
I use the below code to hide the navigation bar.
.navigationBarBackButtonHidden(true).navigationBarHidden(true).navigationBarTitle("")
The above code work in another view but not working in Dashboard.
When I move to another view and come back to the dashboard then the navigation bar hides properly.
I also try this
NavigationLink(destination: MainTabBarView().navigationBarBackButtonHidden(true).navigationBarHidden(true).navigationBarTitle(""), isActive: $isPushHome) but no luck.

You have also another options in the toolbar.
Please try the following code :
var body: some View {
NavigationView {
VStack{
Text("Content").font(.largeTitle)
Spacer()
}
.padding()
.navigationBarTitleDisplayMode(.inline)
.toolbar(content: {
ToolbarItem(placement: .navigationBarTrailing){
Button(action: {}, label: {
Text("Test")
})
}
})
.navigationBarBackButtonHidden(true)
}
}

Related

SwiftUI ScrollView - How to scroll up and down using arrow keys?

I have a SwiftUI view I wrap in a NSHostingController in a mac app. This view consists of a vertical ScrollView with LazyVStack in it with various content (divided into Section). This content is long so the view is always scrollable.
I'm trying to implement better keyboard navigation, I can navigate buttons using Tab key, but I also want to support basic scrolling using up and down arrow keys.
This is something that works out-of-the-box in AppKit when e.g. using NSTextView in NSScrollView.
How do I enable scrolling up and down using arrow keys for SwiftUI.ScrollView on macOS?
I'm to looking for scrolling to an identifiable element but rather to scroll by x points up and down. Like the NSScrollView works.
Ideally, including modifier keys ALT+Up to page up and CMD+Up to scroll to the top.
struct ContentView: View {
var body: some View {
ScrollView(.vertical) {
LazyVStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
Section("Lorem Ipsum") {
Text(Strings.longText)
}
}
.padding()
}
}
}

SwiftUI unintentional Root View navigation from sheetView

I'm having an issue with navigation view and using a popup view to add a core data object. When I dismiss the view instead of going one view back it goes to the root view. This is frustrating especially when you are 5 views in and just want to go back one view.
I've tried many ways to dismiss the view. I have tried different ways of calling and dismissing the popup view including:
Dismissing view:
#Environment(\.presentationMode) var presentationModel
then
self.presentationMode.wrappedValue.dismiss()
Calling and Dismissing view:
#State var showAddObjectView = false
.navigationBarItems(trailing: Button(action: {
self.showAddObjectView.toggle()
}) {
Image(systemName: "plus").imageScale(.large).font(Font.system(.body)).padding(15).accentColor(Color("BlackWhite"))
}.sheet(isPresented: $showAddObjectView) {
AddMoodView(showAddMood: $showAddMood, person: person).environment(\.managedObjectContext, self.managedObjectContext)
})
Then in the sheet view:
#Binding var showAddObjectView: Bool
Then on the save button:
self.showAddMood = false

Is there a way not to show a window for a SwiftUI-lifecycle macOS app?

I'm looking to not show a window for a SwiftUI application on macOS. The app uses SwiftUI's application lifecycle and only runs in the status bar. Showing a window on start up is unnecessary. I'm unsure however how to get around the WindowGroup. There's no such a thing as an EmptyScene and putting an EmptyView inside the WindowGroup of course creates an empty window.
#main
struct MyApp: App {
#NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
I basically only need the app delegate. I'm guessing using the default AppKit lifecycle makes more sense, but if there is a way to use SwiftUI's lifecycle, I'd love to know.
In your AppDelegate, do the following in your applicationDidFinishLaunching:
func applicationDidFinishLaunching(_ notification: Notification) {
// Close main app window
if let window = NSApplication.shared.windows.first {
window.close()
}
// Code continues here...
}
For example:
class AppDelegate: NSObject, NSApplicationDelegate {
var popover = NSPopover.init()
var statusBar: StatusBarController?
func applicationDidFinishLaunching(_ notification: Notification) {
// Close main app window
if let window = NSApplication.shared.windows.first {
window.close()
}
// Create the SwiftUI view that provides the contents
let contentView = ContentView()
// Set the SwiftUI's ContentView to the Popover's ContentViewController
popover.contentSize = NSSize(width: 160, height: 160)
popover.contentViewController = NSHostingController(rootView: contentView)
// Create the Status Bar Item with the above Popover
statusBar = StatusBarController.init(popover)
}
}
You should be able to do something like this:
var body: some Scene {
WindowGroup {
ZStack {
EmptyView()
}
.hidden()
}
}
If you app has settings (who doesn't?), you can do like this:
#main
struct TheApp: App {
#NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
Settings {
SettingsView()
}
}
}
The app uses SwiftUI's application lifecycle and only runs in the status bar.
Use a MenuBarExtra
scene to render a persistent control in the system menu bar with the native SwiftUI lifecycle. (Xcode 14.2, macOS Ventura)
#main
struct MyStatubarMenuApp: App {
var body: some Scene {
// -- no WindowGroup required --
// -- no AppDelegate needed --
MenuBarExtra("😎") {
Text("Hello Status Bar Menu!")
Divider()
Button(…)
MyCustomSubmenu()
}
}
}
Note: Add and set Application is agent = YES in Info.plist for the app icon to not show on the dock.

SwiftUI 2.0 disable window's zoom button on macOS

I am writing a small App for the Mac..
I need to disable to (Green Button) for full screen.
I am using SwiftUI App not AppKit App Delegate
Cant find how to disable the Full Screen Button for my app.
Any thoughts?
Because no one answered with a cleaner SwiftUI only version:
struct ContentView: View {
var body: some View {
HostingWindowFinder { window in
window?.standardWindowButton(.zoomButton)?.isHidden = true //this removes the green zoom button
}
Text("Hello world")
}
}
struct HostingWindowFinder: NSViewRepresentable {
var callback: (NSWindow?) -> ()
func makeNSView(context: Self.Context) -> NSView {
let view = NSView()
DispatchQueue.main.async { [weak view] in
self.callback(view?.window)
}
return view
}
func updateNSView(_ nsView: NSView, context: Context) {}
}
HostingWindowFinder concept taken from https://lostmoa.com/blog/ReadingTheCurrentWindowInANewSwiftUILifecycleApp/

Popover does not appear when closed during TextField edit

I want to edit objects using popovers in my macOS application. But for some reason the popover does not appear anymore, when it was closed the popover while editing a TextField. (see gif bellow)
Any ideas, why this is happening?
Code:
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
SubView()
SubView()
SubView()
}.padding()
}
}
struct SubView: View {
#State var showPopover = false
var body: some View {
VStack {
Text("Label")
}.onTapGesture {
self.showPopover = true
}
.popover(isPresented: $showPopover, arrowEdge: .trailing) {
Popover()
}
}
}
struct Popover: View {
#State var test: String = ""
var body: some View {
TextField("Text", text: $test)
}
}
It looks like it is not enough one event to resign editor first responder and close previous popover, so state of following popover is toggled, but new popover is not allowed, because previous is still on-screen.
The following workaround is possible (tested & works with Xcode 11.2)
}.onTapGesture {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
self.showPopover = true // delay activating new popover
}
}
Also it is possible to consider design approach when there is only one popover bindable to models of different subviews (which seems to me more appropriate) and manageable by the one state.

Resources