当前位置:   article > 正文

自定义命令到‘查看‘菜单_sidebarcommand

sidebarcommand

我正在尝试更改macOS SwiftUI应用程序中的默认命令。我想附加一些自定义命令到'查看'菜单,但我不能让它工作。

这就是我所尝试的:

  1. @main
  2. struct MyApp: App {
  3. var body: some Scene {
  4. WindowGroup {
  5. AppView()
  6. .environmentObject(AppModel.shared)
  7. .environment(\.managedObjectContext, AppModel.shared.cloudKitCoordinator.coreDataStack.viewContext)
  8. }
  9. .commands {
  10. ViewCommands()
  11. SidebarCommands()
  12. ElementCommands()
  13. NavigationCommands()
  14. }
  15. }
  16. }
  17. struct ViewCommands: Commands {
  18. var body: some Commands {
  19. CommandMenu("View") {
  20. Button("Do something View related") {}
  21. }
  22. }
  23. }

“创建第二个”菜单,而不是“附加到另一个”菜单:

有没有人有幸改变了默认的命令菜单的,或者这只是一个部分的快速用户界面,仍然有点原始?

使用CommandGroup,它具有附加或替换现有菜单的init选项:

  1. .commands {
  2. CommandGroup(before: CommandGroupPlacement.newItem) {
  3. Button("before item") {
  4. print("before item")
  5. }
  6. }
  7. CommandGroup(replacing: CommandGroupPlacement.appInfo) {
  8. Button("Custom app info") {
  9. // show custom app info
  10. }
  11. }
  12. CommandGroup(after: CommandGroupPlacement.newItem) {
  13. Button("after item") {
  14. print("after item")
  15. }
  16. }
  17. }

Commands in SwiftUI

24 Nov 2020

This week we will talk about another new API that Apple released this year during WWDC 20. Replacing AppDelegate with the new SwiftUI App Lifecycle brings us tons of new APIs that we can use to replace old functionality with a brand new declarative API. One of those APIs is commands, which we will cover today.

Commands are realized in different ways on different platforms. The main menu uses the available command menus and groups to organize its main menu items on macOS. Each menu is represented as a top-level menu bar menu. Each command group has a corresponding set of menu items in one of the top-level menus, delimited by separator menu items.

On iPadOS, commands with keyboard shortcuts are exposed in the shortcut discoverability HUD that users see when they hold down the Command key.

To learn more about implementing keyboard shortcuts, take a look at my “Keyboard shortcuts in SwiftUI” post.

  1. @main
  2. struct TestProjectApp: App {
  3. var body: some Scene {
  4. WindowGroup {
  5. ContentView()
  6. }.commands {
  7. CommandMenu("First menu") {
  8. Button("Print message") {
  9. print("Hello World!")
  10. }.keyboardShortcut("p")
  11. }
  12. }
  13. }
  14. }

As you can see in the example above, you can attach the commands modifier to any scene in your app and provide a CommandBuilder closure. CommandBuilder is a function builder like ViewBuilder, but instead of views, it builds commands. You can use primitive command types provided by SwiftUI to compose them together and build your own unique main menu experience.

A scene is a part of an app’s user interface with a lifecycle managed by the system. To learn more take a look at my “Managing scenes in SwiftUI” post.

CommandMenu is a primitive command type that accepts a title for your menu item and a ViewBuilder closure that will be used to build menu items. You can use Button, Picker, Divider, Toggle, and other SwiftUI views to build your command view hierarchy.

  1. @main
  2. struct TestProjectApp: App {
  3. @State private var filter = 1
  4. var body: some Scene {
  5. WindowGroup {
  6. ContentView()
  7. }.commands {
  8. CommandMenu("First menu") {
  9. Button("Print message") {
  10. print("Hello World!")
  11. }.keyboardShortcut("p")
  12. Button("Print second message") {
  13. print("Second message!")
  14. }
  15. Divider()
  16. Button("Print third message") {
  17. print("Third message!")
  18. }
  19. Picker(selection: $filter, label: Text("Filter")) {
  20. Text("Option 1").tag(1)
  21. Text("Option 2").tag(2)
  22. Text("Option 3").tag(3)
  23. }
  24. }
  25. }
  26. }
  27. }

There can be some situations where you need to reuse command types. You can do that by defining your own commands type by conforming to Commands protocol. This approach allows you to reuse your commands.

  1. struct SortingCommands: Commands {
  2. @Binding var sorting: Int
  3. var body: some Commands {
  4. CommandMenu("Sort") {
  5. Picker(selection: $sorting, label: Text("Sorting")) {
  6. Text("Option 1").tag(1)
  7. Text("Option 2").tag(2)
  8. Text("Option 3").tag(3)
  9. }
  10. }
  11. }
  12. }
  13. @main
  14. struct MyApp: App {
  15. @State private var sorting = 1
  16. var body: some Scene {
  17. WindowGroup {
  18. ContentView()
  19. }.commands {
  20. SortingCommands(sorting: $sorting)
  21. }
  22. }
  23. }

Now we know how to create new command menus. What if we need to add the menu item to the existing system provided menu or replace it. For this particular case, SwiftUI provides us CommandGroup type, which allows us to insert new command items before, after or even replace the system provided item. Let’s see how we can use it.

  1. @main
  2. struct TestProjectApp: App {
  3. var body: some Scene {
  4. WindowGroup {
  5. ContentView()
  6. }.commands {
  7. CommandGroup(before: CommandGroupPlacement.newItem) {
  8. Button("before item") {
  9. print("before item")
  10. }
  11. }
  12. CommandGroup(replacing: CommandGroupPlacement.appInfo) {
  13. Button("Custom app info") {
  14. // show custom app info
  15. }
  16. }
  17. CommandGroup(after: CommandGroupPlacement.newItem) {
  18. Button("after item") {
  19. print("after item")
  20. }
  21. }
  22. }
  23. }
  24. }

As you can see in the example above, we create CommandGroup and pass it a CommandGroupPlacement, which will be used as an anchor point for inserted or replaced items. CommandGroupPlacement provides us with many system command locations like newItem, saveItem, printItem, undoRedo, pasteboard, windowArrangement, help, etc.

SwiftUI also provides us a few ready to use commands for searching, editing and transforming text that you can enable by using commands modifier and attaching it to any scene you need.

  1. @main
  2. struct TestProjectApp: App {
  3. var body: some Scene {
  4. WindowGroup {
  5. ContentView()
  6. }.commands {
  7. TextEditingCommands()
  8. TextFormattingCommands()
  9. }
  10. }
  11. }

Conclusion

This week, we learned about another new declarative API that SwiftUI provides to build your macOS app’s main menu. I hope you enjoy this declarative API that allows us to maintain a single codebase for different platforms. Feel free to follow me on Twitter and ask your questions related to this article. Thanks for reading, and see you next week!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/777579
推荐阅读
相关标签
  

闽ICP备14008679号