An agent based (menu bar) app using storyboards

This is something that not many people have come across, but I’ve had the opportunity to participate in an open source project that was delivered as an agent / menu bar app in OS X using Swift and Storyboards, and would like to share my experiences during the development process. The sample source code is located here.

Real world example: Beddy Butler is a menu-bar app that helps you go to sleep earlier at night. This is a real world scenario where I used Storyboards + Swift to implement the project. This repository is open source and public, and you are welcome to contribute to it and improve it.

What are Agents?

In OS X, an Agent is an app that will not show a dock icon, but will instead show to the user in the menu / status bar (at the top-right corner of your screen). It’s usually common to adopt this behaviour for apps that need to run mostly in the background (although it is also possible to create apps that run entirely in the background only if you don’t need any user interaction).

Why use Storyboards?

Perhaps you haven’t thought about this before. You may have concluded that an agent based app is so small and has a very small amount of user windows compared to other apps, so why would you bother?. I would say to that that since storyboards have been created to reduce boilerplate coding and give the developer a better understanding of the app’s navigation and interaction between windows (among other features), even the smallest app can benefit from using storyboards, and make life much simpler for us!.

Creating a Sample App

Project creation

To create an agent based App you can simply create a project as OS X Cocoa Application. Because we haven’t told Xcode that our app will be an agent yet, Xcode will offer all the regular options that we can have for any other App on creation, so we can select that we would like the App to be written in Swift and using Storyboards of course!

1. Agent Based App Creation

Next we’ll proceed to add a new string to our Info.plist file. Search for:

Application is agent (UIElement)

and set it to YES

AgentBased2

The AppDelegate

Because we are working with Storyboards and don’t need to make additional connections to xib files etc, we only need to worry about two additional new items that we should create when our app starts: the NSStatusItem and the NSMenu

Our app doesn’t have a starting window or view controller, so we need to create an outlet to the NSMenu in the AppDelegate, which will be our starting point in the App. We’ll also need to declare parent item that will hold the menu (NSStatusItem), so that we can configure it.

    @IBOutlet weak var menu: NSMenu!
    var statusItem: NSStatusItem?

Now we’ll configure the status bar item’s length, title, image (optional), and finally we’ll attach our menu to the status Item. All this should happen once the App is launching:

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Make a status bar that has variable length (as opposed to being a standard square size)
        // -1 to indicate "variable length"
        self.statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-1)
        
        // Set the text that appears in the menu bar
        self.statusItem!.title = "Star!"
        self.statusItem?.image = NSImage(named: "Star")
        self.statusItem?.image?.size = NSSize(width: 20, height: 18)
        self.statusItem?.length = 70
        // image should be set as tempate so that it changes when the user sets the menu bar to a dark theme
        self.statusItem?.image?.template = true
        
        // Set the menu that should appear when the item is clicked
        self.statusItem!.menu = self.menu
        
        // Set if the item should change color when clicked
        self.statusItem!.highlightMode = true
        
    }

Linking the Menu Bar to the App Delegate (via the IBOutlet)

Delete the window controller and the view controller that show by default. We wont need them as we only need to work with the menu. Don’t worry, we’ll create more view controllers and fill our Storyboard later on.

We can then use the already created menu as our starting point in the App. We need to link the Menu to the AppDelegate so that it’s displayed as soon as the App starts. To do this, we can select the Parent NSMenu item (as shown in the picture below). We will see new options for this menu in the Connections Inspector, from which we select a New Referencing Outlet. We finally drag from there to the App Delegate.

Because we already created the public menu variable in AppDelegate, this action will trigger a mini context menu over App Delegate that will show “menu” (our menu variable in AppDelegate), we then select this variable, and that’s it, our Menu is linked to the App Delegate and ready to be the starting point of our App.
AgentBasedApp-2

 

The View Controllers and the Storyboard workflow

Now we can start creating the fun part and our Storyboards can come to live!

At this point it’s up to you how to create a storyboard sequence that start directly from the menu items. The most common features I would think about adding would be A preferences window and the About window. Do notice that when I say “window” I’m not implying that you’ll have to create any NSWindowController or NSWindow. The NSMenuItem and the storyboard are in charge of this, and you will simply need to add View Controllers that you need.

As a good start, you can simply add one view controller, place a label on it and drag from the first menu item to that view controller. This will create a segue which you should usually choose to be presented as either modal or show.

This is an example of a completed storyboard with a template to get started (you can download it from my Github project). This template features a Preferences window with a Tab View Controller and an About window with a single View Controller.

AgentBasedApp-3

Once you run the App, Xcode will place  the App icon and title on your Mac’s top menu bar as expected. You should see a start icon and the title “Star!” If you’re running the sample App I created.

AgentBasedApp-4

Final thoughts

Storyboards can be used to created about any kind of App for the Mac, and I hope this article has illustrated a good example of using them to create an App that would otherwise be created by using Nib files only.

I’ve covered most of the setup required to create a simple Menu Bar Application using Storyboards. Feel free to write your comments or feedback about the article below.

Happy coding!

David

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s