Showing a Sheet When Choosing a Menu Item

VoodooPad is a Mac app for building a personal wiki. When you create a new wiki page in VoodooPad, a sheet opens for you to name the page.

I wanted something similar in one of my Mac app projects that uses storyboards. I created a view controller for the sheet. I added a toolbar button, made a connection to the sheet’s view controller and chose Sheet from the list of available storyboard segues.

One of Apple’s guidelines for Mac user interfaces is that every toolbar button should have a menu item. So I created a menu item to show the sheet and made a connection from the menu item to the sheet’s view controller. But there was no Sheet segue available. The only available segues were Custom, Show, and Modal. How do you show a sheet after choosing a menu item?

Solution Overview

You must perform the following steps to show a sheet from a menu in a Mac app using storyboards:

  1. Give the sheet’s view controller a storyboard ID to identify the view controller.
  2. Add an action to the main view controller that creates an instance of the sheet view controller and presents it as a sheet.
  3. Connect the menu item to the action.

Give the Sheet’s View Controller a Storyboard ID

The sheet’s view controller needs a storyboard ID so you can create an instance of the view controller in your code. Select the sheet’s view controller from the storyboard and open the identity inspector.

ViewControllerStoryboardID

Enter the ID in the Storyboard ID text field. Remember the ID because you will need it when writing the code to show the sheet.

Add an Action to the Main View Controller to Show the Sheet

You must write an action in the main view controller to show the sheet. When someone chooses the menu item, your app performs the action. The main view controller is the controller that shows the window’s content.

The first step is to get the storyboard where the sheet view controller resides. I’m going to assume the main view controller and sheet view controller reside in the same storyboard so I can use the main view controller’s storyboard property to get the storyboard.

After getting the storyboard, call its instantiateController method, supplying the sheet view controller’s storyboard ID. After instantiating the sheet view controller, call the presentAsSheet method, supplying the sheet view controller.

@IBAction func showSheet(_ sender: AnyObject) {
    if let theStoryboard = storyboard,
        let sheetViewController = 
            theStoryboard.instantiateController
                (withIdentifier: "sheetViewControllerID") 
                as? MySheetViewController {

        presentAsSheet(sheetViewController)
    }
}

Connect the Menu Item

The last step is to connect the menu item to the action you wrote to show the sheet. Make a connection from the menu item to the First Responder object in the Application scene. A long list of actions opens. Choose the action you created to show the sheet.

When someone chooses the menu item, your app will call the action you wrote. Calling the action will show the sheet.