Core Controls in Mac OS X: Part 1/2

Ernesto García Ernesto García

Core Controls in OS X Applications

If you’re an iOS developer and you’re interested in learning about Mac development, you’re in luck – with your iOS skills, you’ll find it quite easy to learn!

Many of the Cocoa Touch APIs and design patterns you know and love like NSString, NSMutableArray, and delegates have direct equivalents in Mac development. You’ll feel right at home!

However, one big difference with Mac development are there are different controls. Gone are UIButtons and UITextFields – instead there are similar (but slightly different) Mac variants.

This tutorial will introduce you to some of the more common user interface controls of OS X — the foundation upon which most Mac apps are built. You’ll learn about these controls, as well as the methods and properties you’ll need to understand in order to get up and running as a developer! :]

In this tutorial, you’ll be creating a simple Mac application like the popular game Mad Libs. Mad Libs is a word game where you can insert different words in a block of text in order to create a story — which often has hilarious results!

Once you’ve completed both parts of this tutorial, you’ll have a fundamental understanding of the following controls:

  • Labels and Text Fields
  • Combo Boxes
  • Popup Buttons
  • Text Views
  • Sliders
  • Date Pickers
  • Buttons
  • Radio Buttons
  • Check Buttons
  • Image Views

Before you go through this tutorial, you should go through our How to Make a Simple Mac App Tutorial to learn the basics of Mac development.

The best way to learn any new programming platform is to dive right in and get started — so without further ado, here’s your introduction to Core Controls in Mac OS X! :]

Getting Started

Launch Xcode, and choose File\New\Project. When the Choose a template dialog appears, select OS X\Application\Cocoa Application, which is the template you use to create an app with a GUI on the Mac. Then click Next.

In the project options dialog, enter MadLibs as the product name. Also enter a unique company identifier and make sure Use Automatic Reference Counting is checked, as below:

Note: Automatic Reference Counting works on the Mac the same way it does on iOS. If you’re new to ARC or want to learn more about how it works, check out our tutorial on the matter!

Click Next. Finally, choose a location where you’d like to save your new project, and click Create.

Once Xcode has finished generating the project files, you’ll be presented with the main Xcode window. Go ahead and click Run in the toolbar. If all goes well, you should see the following:

You’ve built a working application — without any coding at all. The window is empty right now, but you’re going to fill it up with some controls and make it look amazing! :]

Click on MainMenu.xib in the project explorer, and you’ll see a window which already contains a view, referred to as the window’s content view. You’re going to create a view controller that will be the owner of this view.

From the File menu choose New\File, or alternately you can use the keyboard shortcut Command + N. When the Choose a template dialog appears, select OS X\Cocoa\Objective-C class, as shown below:

Click Next to move on to the the file options dialog. Enter RootViewController as the Class and make it a subclass of NSViewController. Make sure With XIB for user interface is NOT checked, then click Next.

Finally, click Create to save the new view controller.

Note: the reason that you did not check With XIB for user interface is because this view controller is going to be responsible for the Main Window’s view, which is already made for you in MainWindow.xib.

Now you need to create an instance of your new view controller and associate the Main Window’s view with the view controller. Here, you have two choices — you can do it directly in code, or you can do it the quick and easy way: by using the Interface Builder! :]

Note: If you would like to learn how to create an instance of a view controller in code, please have a look at the How to Make a Simple Mac App tutorial.

Select MainMenu.xib in the project explorer to open it in Interface Builder. In the lower right-hand corner of the window, you’ll find the the Object Library palette. In the Object Library palette, find View Controller and drag it to the Objects palette on the left-hand side of the window, like so:

By default, this view controller object is an instance of NSViewController, but you’ll need this to be an instance of your RootViewController class instead — you will change that right now.

To do this, click on the newly created view controller object, go to the utilities palette and then select the identity inspector tab. Rename the class to RootViewController, as in the screenshot below:

In order to make your newly created view controller the owner of the window’s content view, you’ll need to connect its view outlet to the main window’s content view.

To do that, select the main window in the Objects palette to display it on the screen, and then select your view controller object. Then, go back to the utilities palette and select the connections inspector tab. From the Outlets section, click and drag the view outlet to the main window. This sequence of events is illustrated in the screenshot below:

And that’s it! You’ve now configured your app to instantiate an instance of your RootViewController class, and you’ve made it the owner of the main window’s content view. And you still haven’t written a single line of code! :]

If you’ve followed the above instructions, then everything should be hooked up properly. But before you go any further, take a minute to ensure that everything’s working by following the steps below! :]

You’re going to override awakeFromNib in your RootViewController class, since this method is part of an object’s life cycle when it’s instantiated from a XIB file. If everything has been connected correctly, then this method will be called when the application runs, and the view controller should have a view associated with it.

Open RootViewController.m and add the following:

-(void)awakeFromNib
{
    NSLog(@"View controller instance with view: %@", self.view);
}

This will simply output some debug code to the console to indicate that (a) this code is called, and (b) that the associated view is valid.

Buld and run your app. In the Output pane of the Debug area, you should a message similar to the following:

MadLibs[29008:303] View controller instance with view: <NSView: 0x101a0ef40>

If you see the line above, then you’ve verified that both the view and the view controller have been instantiated, and the two are connected properly!

Now that the basic framework has been laid down, you can now move on to the main focus of this tutorial — adding controls to your app! :]

Each of the remaining steps in this tutorial will focus on a single, different control. You’ll learn the basics of each control, and then implement each one in the Mad Libs app to try it out.

Note: In this tutorial, you’re using Auto Layout, a new feature introduced in OS X 10.7 and iOS 6. If you’re not familiar with this feature, you can learn more by reading Beginning Auto Layout in iOS 6 by Matthijs Hollemans. It’s focused on iOS, but Auto Layout works exactly the same in OS X!

NSControl – The Building Block of Controls

NSControl is the foundation upon which all other controls are built. NSControl provides three features which are pretty fundamental for user interfaces: drawing controls on the screen, responding to user events, and sending action messages.

As NSControl is an abstract superclass, it’s entirely possible that you’ll never need to use it directly within your own apps. All of the common controls are descendants of NSControl, and therefore inherit the properties and methods defined in NSControl.

The most common methods used for a control are getting and setting the value of that control, as well as enabling or disabling the control itself. Have a look at the details behind these methods below:

Setting The Control’s Value

If you need to display information using a control, you’ll usually do this by changing the control’s value. Depending on your needs, the value can be a string, a number or even an object. In most circumstances you’ll use a value which matches the type of information being displayed, but NSControl allows you to go beyond this and set several different value types!

The methods for getting and setting a control’s value are:

// getting & setting an string
NSString *myString = [myControl stringValue];
[myControl setStringValue:myString];
 
// getting & setting an integer
NSInteger myInteger = [myControl integerValue];
[myControl setIntegerValue:myInteger];
 
// getting & setting a float
float myFloat = [myControl floatValue];
[myControl setFloatValue:myFloat];
 
// getting & setting a double
double myDouble = [myControl doubleValue];
[myControl setDoubleValue:myDouble];
 
// getting & setting an object
id myObject = [myControl objectValue];
[myControl setObjectValue:myObject];

Enabling & Disabling a Control

Enabling or disabling a control based on the current state of an app is a very common UI task. When a control is disabled, it will not respond to mouse and keyboard events, and will usually update its graphical representation to provide some visual cues that it is disabled, such as drawing itself in a lighter color.

The methods for enabling and disabling a control are:

// disable a control
[myControl setEnabled:NO];
 
// enable a control
[myControl setEnabled:YES];
 
// get a control's enabled state
BOOL isEnabled = [myControl isEnabled];

Okay, that seems pretty easy — and the great thing is that these methods are common to all controls; they’ll all work the same way for any control you use in your UI.

Now it’s time to take a look at the more common user interface controls of OS X! :]

Field of Dreams – NSTextField

One of the most common controls in any UI is a field that can be used to display or edit text. Almost any modern application will need to display some sort of text, such as a RSS reader, a Twitter client, or an address book, and almost all applications require some sort of text enty to log in, change settings, or to provide other inputs to the app.

The control responsible for this functionality in OS X is NSTextField.

NSTextField is used for both displaying and editing text. You’ll notice this is quite different than iOS, where UILabel is used to display text, and UITextField to edit it. In OS X, these two controls are combined into one, and the behaviour of the control is modified via setting the control’s properties.

If you want a text field to be a label, you simply set it as non-editable. To make the text field editable — yup, you simple set the control to be editable! These properties can either be modified programmatically, or by setting the relevant property through the Interface Builder.

To make your coding life just a little easier, Interface Builder actually provides several pre-configured controls for displaying and editing text which are all based on NSTextField. These pre-configured controls can be found in the Object Library, and are described in the graphic below:

So now that you’ve learned about the function of NSTextField, you can now add one to your Mad Libs application! :]

Living in the Past — A Past Tense Verb

In the Mad Libs application you’ll be building, you will add various UI controls which will allow the user to blindly construct a funny sentence, without knowing the final result. Once the user has finished, your app will combine all the different parts and display the result, hopefully with some comedic value. The more creative the user is, the more fun they’ll have! :]

The first control you’ll add is a text field where the user can enter a verb to be added to the sentence, as well as a label to inform the user what the text field is for.

Select MainMenu.xib in the project explorer to open it in Interface Builder, and then select the Main Window. In the Object Library palette, locate the Label control and drag it onto the window.

Next, locate the Text Field control and drag it onto the window, placing it to the right of the label. Double-click the label to edit the default text, and change it to Past Tense Verb:.

You should now have something similar to this:

Later on, you’re going to need to interact with the text field, and to do this you’ll need a property exposed on the view controller.

To create this property and connect it so that you can work with it, open the assistant editor — making sure that RootViewController.m is selected — and Ctrl-Drag the text field to the private interface to create a new property, like shown below:

In the popup window that appears, name the Outlet pastTenseVerbTextField, and click Connect, as shown in the image below:

And that’s it! You now have an NSTextField property in your view controller that is connected to the text field in the main window.

You know, it would be great to display some sample default text when the app launches, in order to give the user an idea of what to put in the field. Since everyone loves to eat, and food related Mad Libs are always the most entertaining, the word ate would be a tasty choice here! :]

A good place to put this is inside awakeFromNib that you created above. To change the text field’s default value, simply use the setStringValue method you learned about earlier.

Add the following code to the end of awakeFromNib:

// Set the default text for the pastTenseVerbTextField property
[self.pastTenseVerbTextField setStringValue:@"ate"];

Build and run your app. You should see the two controls you’ve just added, and the text field should display the word ate, as below:

Okay, that takes care of a single input with a default value. But what if you want to provide a list of values that the user can select from?

Combo Boxes to the rescue! :]

The Value Combo – NSComboBox

A combo box is interesting — and quite handy — as it allows the user to choose one value from an array of options, as well as enter their own text.

It looks similar to a text field in which the user can type freely, but it also contains a button that allows the user to display a list of selectable items. You can find a solid example of this in OS X’s Date & Time preferences panel:

Here, the user can select from a predefined list, or enter their own server name, if they wish.

The control responsible for this in OS X is NSComboBox.

NSComboBox has two distinct components: the text field where the user can type, and the list of options which appear when the embedded button is clicked. You’re able to control the data in both parts separately.

To get or set the value in the text field, simply use the stringValue and setStringValue methods covered earlier. Hooray for keeping things simple and consistent! :]

Providing options for the list is a little more involved, but still relatively straightforward. You can call methods directly on the control to add elements in a manner similar to NSMutableArray, or you can use a data source — anyone familiar with iOS programming and UITableViewDataSource will feel right at home!

Method 1 – Calling Methods Directly On The Control

NSComboBox contains an internal list of items, and exposes several methods that allow you to manipulate this list, as follows:

// Add an object to the list
[myComboBox addItemWithObjectValue:anObject];
 
// Add an array of objects to the list
[myComboBox addItemsWithObjectValues:@[objectOne, objectTwo, objectThree]];
 
// Remove all objects from the list
[myComboBox removeAllItems];
 
// Remove an object from the list at a specific index
[myComboBox removeItemAtIndex:3];
 
// Get the index of the currently selected object
NSInteger selectedIndex = [myComboBox indexOfSelectedItem];
 
// Select an object at a specific index
[myComboBox selectItemAtIndex:1];

That’s relatively straightforward, but what if you don’t want your options hardcoded in the app — such as a dynamic list that is stored outside of the app? That’s when using a datasource comes in really handy! :]

Method 2 – Using A Data Source

When using a data source to populate the combo box, the control will query the data source for the items it needs to display as well, as any necessary metadata, such as the number of items in the list.

To use a data source, you’ll need to implement the NSComboBoxDataSource protocol in your class. From there, it’s a two-step process to configure the combo box to use the data source.

First, call the control’s setDataSource method, passing an instance of the class implementing the protocol; usually “self”. Then call the control’s setUsesDataSource method, passing YES as the parameter.

In order to conform to the protocol, you’ll need to implement the following two methods:

// Returns the number of items that the data source manages for the combo box
- (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox
{
    // anArray is an NSArray variable containing the objects
    return [anArray count];
}
 
// Returns the object that corresponds to the item at the specified index in the combo box
- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index
{
    return [anArray objectAtIndex:index];
}

Finally, whenever you need to reload the data in a combo box which is using a data source, simply call reloadData().

Which Method To Use?

If your list of items is relatively small and you don’t expect it to change that often, adding items once to the internal list is probably the best choice. But if your list of items is large or dynamic, it can often be more efficient to handle it yourself using a data source.

Now that you’ve covered the fundamentals of the combo box, move on to implement one in your app! :]

The Singles Bar — A Singular Noun

In this section you’ll add a combo box to your Mad Libs application, to allow the user to choose from a list of singular nouns (or allow them to enter their own).

To do this, first add a Label to the app so that the user knows what the control is for. Select the MainMenu.xib in the project explorer to open it in Interface Builder, and then select the Main Window.

In the Object Library palette, locate the Label control and drag it onto the window. Double-click it to edit it’s default text, changing it to Singular Noun:.

Next, add the combo box that will provide the users with the list of choices. Locate the Combo Box control and drag it onto the window, placing it to the right of the label.

Your window should now look like this:

Now you need to add an NSComboBox property to the view controller so you can populate the default items, and later access it via code to read the user’s selection.

To do this, use the same technique you used for the text field: select the assistant editor (making sure RootViewController.m is selected) and Ctrl-Drag the combo box to the RootViewController.m to create a new property, just like in the screenshot below:

In the popup window that appears, name the property singularNounCombo.

Now the NSComboBox property is connected to the combo box control! Now, if you only had some data to populate the list! :] Time to add some.

Open RootViewController.m in the code editor and add the following property declaration directly below the singularNounCombo property:

@property (nonatomic,strong) NSArray *singularNouns;

Inside awakeFromNib, add this to the bottom:

// Setup the combo box with singular nouns
self.singularNouns = @[@"dog", @"muppet", @"ninja", @"fat dude"];
[self.singularNounCombo addItemsWithObjectValues:self.singularNouns];
[self.singularNounCombo selectItemAtIndex:2];

The first line initializes an array with four strings. The second line adds those items to the combo box using one of the methods covered earlier. Finally, the combo box is asked to select the item at index 2.

Build and run the application to see your combo box in action!

Great — it looks as though everything is working just right. Once the app has launched, the combo box selects the second item as the default. If you click on the combo box, you can then view and select any of the other items.

But what if you want to present the user with a list of choices, but not allow them to enter their own text? Read on — there’s a control for that as well! :]

Pop Goes the Weasel — NSPopUpButton

The pop up button allows the user to choose from an array of options, but without giving the user the option of entering their own value in the control. The control responsible for this in OS X is NSPopupButton.

Pop up buttons are incredibly common in OS X, and you can find them in almost every application — including the one that you’re using right now: Interface Builder! :] You’re using the pop up button to set many of the properties on the controls you’re using in this tutorial, as in the screenshot below:

Filling the Spaces — Adding Items To Pop Up Buttons

As you might expect, adding items to NSPopUpButton is similar to adding items to NSComboBox — except that NSPopUpButton doesn’t support using a data source for the content of the control. NSPopUpButton maintains an internal list of items and exposes several methods allowing you to manipulate it:

// Add an item to the list
[myPopUpbutton addItemWithTitle:@"Pop up buttons rock"];
 
// Add an array of items to the list
[myPopUpbutton addItemsWithTitles::@[@"Item 1", @"Item 2", @"Item 3"]];
 
// Remove all items from the list
[myPopUpbutton removeAllItems];
 
// Get the index of the currently selected item
NSInteger selectedIndex = [myPopUpbutton indexOfSelectedItem];
 
// Select an item at a specific index
[myPopUpbutton selectItemAtIndex:1];

Pretty straightforward, isn’t it? That’s the beauty of the core controls — there are a lot of similarities between them in terms of the methods used to manipulate the controls.

Time to implement a pop up button in your app! :]

The More the Merrier — A Plural Noun

You’ll now add a pop up button to your Mad Libs application which will allow the user to choose between different plural nouns to populate your comical sentence.

Select MainMenu.xib in the project explorer to open it in Interface Builder, and then select the Main Window. In the Object Library palette, locate the Label control and drag it onto the window just beneath the Singular Noun label.

Note: Alternatively, a shortcut is to hold down Option and drag an existing label to duplicate it. This is handy so you can keep the same size and properties of an existing label.

Double-click the control to edit its default text, and change it to Plural Noun:. Next, locate the Pop Up Button control and drag it onto the window, placing it to the right of the label.

Your window should now look like this:

Now you need to add an NSPopUpButton property to the view controller. You’ll use the same technique as before, which should be fairly familiar by now: open the assistant editor, make sure RootViewController.m is selected, and then Ctrl-Drag the pop up button to the RootViewController.m to create a new property. This is illustrated in the screenshot below:

In the popup window that appears, name the property pluralNounPopup:

Okay, now the NSPopUpButton property is connected to the pop up button control. Now you just need some data to populate it!

Open RootViewController.m in the code editor and add the following property declaration directly below the pluralNounPopup property.

@property (nonatomic,strong) NSArray *pluralNouns;

Add the following code to the bottom of awakeFromNib:

// Setup the pop up button with plural nouns
self.pluralNouns  = @[@"tacos", @"rainbows", @"iPhones", @"gold coins"];
[self.pluralNounPopup removeAllItems];
[self.pluralNounPopup addItemsWithTitles:self.pluralNouns];
[self.pluralNounPopup selectItemAtIndex:0];

The first line in the code above initializes an array with four strings. The second line removes any existing items from the pop up button. The third line adds the array of items to the pop up button using some of the methods covered earlier. Finally, the pop up button is instructed to select the first item in the list as the default.

Build and run the application to see the result:

Once the app has launched, note that the pop up button shows the initial item, tacos, and if you click on the pop up button, you’ll see all the other items in the list.

Okay, so you now have two controls that allow the user to select from lists, as well as a control that allows the user to enter a single line of text. But what if you need the user to enter more than a few words in a text field?

Read on to learn about text views! :]

Text is Next – NSTextView

Text views, unlike text fields, are usually the control of choice for displaying rich text. Some implementations even allow for more advanced features such as displaying inline images.

The control responsible for this on OS X is NSTextView.

A great example of an application using all of what NSTextView has to offer is TextEdit, as shown in the screenshot below:

NSTextView is so feature rich that to cover everything would warrant a tutorial of its own, so here you’ll just cover a few of the basic features in order to get you up and running! (Did you just breathe a sigh of relief?) :]

Here are the basic methods you’ll need to work with text views:

// Get the text from a text view
NSString *text = [myTextView string];
 
// Set the text of a text view
[myTextView setString:@"Text views rock too!"];
 
// Set the background color of a text view
[myTextView setBackgroundColor:[NSColor whiteColor]];
 
// Set the text color of a text view
[[myTextView setTextColor:[NSColor blackColor]];

Relatively simple — nothing too shocking here! :]

The String’s the Thing — Attributed Strings

NSTextView has built-in support for NSAttributedString. If you pass an attributed string to a text view, the string will be displayed correctly using all the appropriate attributes such as font, font size, and font color.

Note: An attributed string is a special type of string where you can tag subsets of the string with different attributes – such as its font, it’s color, whether it’s bolded, and so on. To learn all about attributed strings, check out the Attributed Strings chapter in iOS 6 by Tutorials (most of the information in that chapter applies to Mac development as well).

NSTextView has a property called textStorage, whose type is NSTextStorage. NSTextStorage is a semi-concrete subclass of NSMutableAttributedString, which is a fancy way of saying “you can put formatted text in it, and change it later.”

In order to have NSTextView display an attributed string, you actually set the attributed string on the NSTextStorage instance returned by the textStorage property, as shown in the code below:

// Setting an attributed string on the NSTextStorage instance owned by our NSTextView
NSAttributedString *myAttributedstring = ...;
[myTextView.textStorage setAttributedString:myAttributedstring];

So that’s how to set the text view’s (attributed) string – now let’s try it out!

The Phrase that Pays – Adding a Text View

Looks like you have everything you need in order to add a text view to your Mad Libs application! This text view will allow the user to enter a multi-word phrase that will be used in the final rendered Mad Lib.

To add the text view to your application, open MainMenu.xib and then select the Main Window. In the Object Library palette, locate the Label control and drag it onto the window just beneath the Plural Noun label (or duplicate an existing label, as mentioned earlier).

Again, double-click it to edit the default text, changing it to Phrase:. Next, locate the Text View control and drag it onto the window, placing it beside the the label you just created.

Your window should now look like this:

Now you need to add an NSTextView property to the view controller. Again, the same familiar technique is similar to before, but there’s a twist.

Important: Since text views are contained inside scroll views, it’s important you make sure you’ve actually selected the text view before creating the property. To do so, simply click twice on the text view (or select it from the Object navigator from the left). You can check the text view has been selected by inspecting the Type in the popup window.

Once you’re sure you have the text view selected, as before select the assistant editor, make sure RootViewController.m is selected, and Ctrl-Drag the text view to the RootViewController.m. The result is shown below:

In the popup window, name the property phraseTextView, as shown here:

Now that the NSTextView property is connected to the text view control, you can set a default text phrase in the control to again give the user an idea of what to enter here.

Add the following code to the end of awakeFromNib:

// Setup the default text to display in the text view
[self.phraseTextView setString:@"Me coding Mac Apps!!!"];

Build and run the application to see the result! :]

Superb! The Mad Libs application is really starting to take shape now! :]

Next Steps — Where to Go From Here?

Here’s the example project containing all the source code from this first part of the series.

In the second part of this tutorial, you’ll learn about more of the core controls in OS X, including sliders, date pickers, push buttons, radio buttons, check boxes and image views — each of which will be added to your Mad Libs application in order to complete it!

In the meantime, if you have any questions or comments about what you’ve done so far, be sure to let me know in the forums!

Ernesto García
Ernesto García

Ernesto is a Mac and iOS developer from Spain. After 16+ years of experience developing Enterprise applications, now he is an indie developer who focuses on creating great mobile and desktop applications. He's the founder of CocoaWithChurros where he develops Apps for clients as well as his own. You can also find him on Twitter or Github.

User Comments

2 Comments

  • that was a great article

    Just create a project only AppDelegate, no ViewController
    That helped me create a view controller as window's content view and became the owner of the view.
    langzuxiaozi
  • Fabuloso tutorial, simple y directo!
    Rojano

Other Items of Interest

Ray's Monthly Newsletter

Sign up to receive a monthly newsletter with my favorite dev links, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Vote for Our Next Tutorial!

Every week, we alternate between Gaming and Non-Gaming tutorial votes. This week: Non-Gaming!

    Loading ... Loading ...

Last week's winner: How To Make a Tower Defense Game with Swift.

Suggest a Tutorial - Past Results

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in December: The Great CALayer Tour

Sign Up - December

Our Books

Our Team

Tutorial Team

... 57 total!

Update Team

  • Zouhair Mahieddine

... 14 total!

Editorial Team

... 22 total!

Code Team

  • Orta Therox

... 3 total!

Subject Matter Experts

... 4 total!