Chapters

Hide chapters

Catalyst by Tutorials

Third Edition · iOS 15 · Swift 5.6 · Xcode 13.3

Section I: Making a Great iPad App

Section 1: 7 chapters
Show chapters Hide chapters

10. Barista Training: Menu Bar
Written by Marin Bencevic

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

Welcome to barista training! In the next few chapters, you’ll learn all about adding different kinds of bars to your Catalyst app, including the menu bar, toolbars and supporting the touch bar. In this chapter, you’ll trim the default menu bar of the Journalyst app to remove some unnecessary items. You’ll also add new items to delete, share and add new entries. Get out your beans and your fancy hipster oat milk — it’s time to get brewing!

A Free Menu Bar

All Catalyst apps include a default menu bar for free. Open the starter project from the provided materials and run it on macOS. When your app is active, you’ll see its menu bar at the top of your screen. All the standard menus like File, Edit, etc. are already there.

Note: WWDC 2021 introduces a new property in info.plist called UIApplicationSupportsPrintCommand. When set to YES, in your menu bar, under File, it gives you Print… and Export as PDF… options.

Apple sometimes calls the menu bar the “main menu.” That’s how you must think about what actions to put in the menu bar. Like in a video game, the main menu includes general actions the user can perform inside your app.

One thing you must keep in mind is that menu bars aren’t dynamic. They’re built once when the app launches and the items never change during runtime. For more dynamic actions related to specific parts of your app, use context menus as described in Chapter 5, “Adding Some Context.”

The menu bar itself is a nested UIMenu instance. Each UIMenu can contain child menus and commands. Commands are the buttons you can press to do something. They can be enabled or disabled, and each command can specify a keyboard shortcut for easier access.

Commands get executed using something called the responder chain.

The Responder Chain

Open the Edit menu, and you’ll notice that Cut, Copy and Paste are all greyed out. This makes sense: Since nothing is selected, there’s nothing to cut or copy.

Disabled items in Edit menu.
Zoxumwet usasv er Idik wule.

Beyond the Default Menu

You’ll start by trimming some unnecessary items from the menu bar. The menu bar can be changed either in Interface Builder or through code. In this section, you’ll use Interface Builder and, later in the chapter, you’ll learn how to do the same in code.

Main Menu in the storyboard.
Vauh Raro uv zku sropfliajp.

Menu bar without the format menu.
Hiri kuf fuyguok fxe xerjeq teqe.

Inline Section Menu in File menu.
Omqule Hesgeud Jite as Funu kora.

Item 1 Attributes inspector.
Ogov 5 Imjmeyupiz udxnivvup.

@IBAction @objc private func addEntry(
  sender: UIKeyCommand
) {
New Entry's first responder.
Qoy Ijfdh'h sogqp hotcufkit.

New entry in the File menu.
Wud ewpcb ab mvu Buzo quho.

Deleting Entries

Back in Main.storyboard, select Item 2 in the File submenu you added earlier. In the Attributes Inspector, change its Title to Delete Entry and set the Key Equivalent to Shift-Command-Backspace.

@IBAction @objc private func removeEntry(
  sender: UIKeyCommand
) {
Delete Entry in the File menu.
Kufuyu Exjwt ew tza Zeso hike.

// 1
override func validate(_ command: UICommand) {
  // 2
  switch command.action {
  case #selector(removeEntry):
    // 3
    if let mainNavigationController
         = viewController(for: .primary)
         as? UINavigationController,
       let mainTableViewController
         = mainNavigationController.topViewController
         as? MainTableViewController,
       let selectedIndexPath
         = mainTableViewController
         .tableView.indexPathForSelectedRow {
      // 4
      let entry
        = DataService.shared.allEntries[selectedIndexPath.row]
      command.title = "Delete \(entry.dateCreated)"
    } else {
      // 5
      command.title = "Delete Entry"
    }
  default:
    break
  }
}
Delete with a title of date and time.
Mideze gabn u puhva iw boce osq xexe.

Sharing Entries

The menu bar is only one of the potentially many menus you can have in your app. Each UIResponder can add or remove items from their menus. The responder that’s responsible for the menu bar is the application itself, or in other words, the app delegate.

override func buildMenu(with builder: UIMenuBuilder) {
}
guard builder.system == .main else { return }
let shareCommand = UIKeyCommand(
  title: "Share",
  action: #selector(EntryTableViewController.share),
  input: "s",
  modifierFlags: [.command]
)
let shareMenu = UIMenu(
  title: "",
  options: [.displayInline],
  children: [shareCommand]
)
builder.insertChild(shareMenu, atStartOfMenu: .file)
Uncheck in Attributes inspector.
Inwvovj ow Osnvidiceq uhhmuwwug.

Share in File menu.
Rfovo uq Rone hewi.

override func validate(_ command: UICommand) {
  switch command.action {
  case #selector(share):
    if textView.text.isEmpty {
      command.attributes = [.disabled]
    } else {
      command.attributes = []
    }
  default:
    break
  }
}
Disable Share in empty text view.
Cohedku Wyewi aw elkpc nocn riuj.

Key Points

  • Catalyst apps include a default menu bar for free.
  • The menu bar consists of nested menus which contain commands.
  • Each command has a selector that it calls when pressed, and uses the responder chain to enable and disable itself.
  • You add or remove items from the menu bar by dragging over a Main Menu to your app’s storyboard.
  • You can make the same changes in code by overriding buildMenu in the app delegate.
  • Override validate in a UIResponder subclass to change the appearance of a command.

Where to Go From Here?

The Human Interface Guidelines section on menus has some useful tips of which actions to consider for the menu bar, and where to put them.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now