How to collapse sidebar with SwiftUI on Mac - macos

I am building a full screen function which is supposed to hide the navigation bar and the side bar. However, I have only found a way to toggle the sidebar using NSApp.keyWindow?.firstResponder?.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)), with: nil), which is not working well in my case because I cannot detect if the side bar is visible or not on mac (.onDisappear does not seem to be called on mac when the sidebar collapses).
Below is a simplified example of my NavigationView. I did not use NavigationSplitView because it does not work in my case unless I use some nasty hacks (which leads to crashes too).
let data: [String] = createData()
NavigationView {
List(data, id:\.self) { item in
NavigationLink {
DetailView(item)
} label: {
Text(item)
}
}
DetailView("Nothing Selected")
}

Related

Toolbar at bottom on macOS with SwiftUI

On my macOS app, I have a main toolbar at top.
However, I would like to add a new bottom toolbar at bottom (smaller).
Like that for example:
It seems there is no way to do this on macOS as on iOS:
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
// add wine
AddButton()
Spacer()
}
}
=> .bottomBar doesn't exist on macOS.
Well, just before creating a custom view/content with some buttons, I would like to be sure there is no official way to do that on macOS (with SwiftUI only...).

SwiftUI option key alternate menu items on macOS

In many macOS apps, if you open a menu from the main menubar, you can press the option key to change some of the items.
For example in Safari, I can open the File menu, and there is a "Close Tab" item. Pressing option changes it to "Close Other Tabs".
Is there a way to do this with SwiftUI?
I know how to create basic menus, but I don't see a way to detect the option key.
I think in AppKit you use NSMenuItem's isAlternate property.
struct MyApp: App {
var body: some Scene {
WindowGroup {
...
}.commands {
CommandGroup(replacing: .newItem) {
Button { newFolder() } label: { Text("New Folder") }
.keyboardShortcut("n")
...
}
}
Update to Question
I've tried a few more things, and run into two problems.
I can connect a custom object to the end of the NSResponder chain, and the system will call its flagsChanged method when the user presses the option key. However, it will not call this method when a menu is open.
Even if I find a way to observe the option key while the menu is open, changing state used to build a CommandMenu causes the menu to disappear, not rebuild and stay open.
var body: some Commands {
// If the `isOptionDown` property changes when this menu is open,
// SwiftUI doesn't change the menu, it simply closes it.
// That's not how macOS apps usually behave.
CommandGroup(replacing: .pasteboard) {
Button(...)
if optionKeyWatcher.isOptionDown {
Button(...)
} else {
Button(...)
}

How do I stop double clicking a NavigationLink opening a second window view?

Writing a Macos app. The following code just puts up a simple navigation list. Everything is fine with single clicking the Row links and displaying the Detail row.
If you double click the NavigationLink, another window opens with only the Text view on it. During my testing, there was a button to dismiss the view on the detail window, and if clicked, the original window would close leaving this stripped down view open.
I have to assume that no one else is seeing this since I cannot see anything from other people.
Does anyone have any ideas what would cause this to happen?
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
NavigationView {
List(0..<100) { row in
NavigationLink(destination: Text("Detail \(row)")) {
Text("Row \(row)")
}
}
}
}
}
}
Just use sidebar list style explicitly
List(0..<100) { row in
// ... content here
}
.listStyle(SidebarListStyle()) // << here !1
Tested with Xcode 13.2 / macOS 12.1

`onCopyCommand` on macOS is never being called. How to use it?

Does anyone know how to use onCopyCommand / onPasteCommand modifier in SwiftUI on macOS?
I can't make it being called.
No matter where I put it, 'copy / cut / paste` menu items are disabled.
In case you are using a custom view, you need to make sure it is focused.
Currently, the only way I know to focus a view (in SwiftUI) is with the focusable modifier
import SwiftUI
struct MyView {
var body: some View {
VStack {
Text("can be focused by pressing 'TAB'")
}
.focusable()
.onCopyCommand {
return [NSItemProvider(/* some data */)]
}
}
}
Note:
The only way to focus a custom View with focusable() modifier, is with the TAB key. I guess that mouse clicks are not yet supported.
I have got more Info Here

SwiftUI Custom Picker / ComboBox

I am trying to get a customized Picker in SwiftUI for MacOS. The best option I would like to have is a customized view which can be pressed and then shows the Picker options like a ComboBox in AppKit.
Apple achieves that in their Contact books app on Mac or the Sharing dialog of Apple is the same way.
You press the + Button and the selection comes up. Is that possible in SwiftUI?
Edit: This looks very similar like contextMenu in SwiftUI. But how can I set it on left click instead?
Finally found MenuButton which does the trick for SwiftUI in MacOS.
MenuButton(label: Title(), content: {
Button(action: {
print("Clicked an item")
}) {
Text("Menu Item Text")
}
})
.menuButtonStyle(BorderlessButtonMenuButtonStyle())
... with using a custom View Title() for my clickable button.
struct Title: View {
var body: some View {
HStack
{
Text("Title")
}
}
}

Resources