BaseTen Tutorial

This tutorial was originally written by Tim Bedford.

Introduction

If you have read Aaron Hillegass’ book Cocoa Programming for Mac OS X, then this example will be familiar. We are going to create an application much like the one in the chapter on Basic Core Data. If you haven’t read the book, then I recommend you do. It is a great primer to Objective-C and Cocoa. Even if you have a good working knowledge of both, the book makes a good reference.

Before We Start

Before we can begin building a BaseTen application we need to install the tools and frameworks. Open up BaseTen-1.7.dmg. Drag the BaseTen.framework and BaseTenAppKit.framework to the alias of the Frameworks folder. This will copy them into /Library/Frameworks/. Copy BaseTen Assistant and the reference manual where ever you like.

You will also need to have a version of PostgreSQL installed, either on your development machine, or another accessible over the network. PostgreSQL 8.3 has been used to create this tutorial. A ready compiled version for Mac OS X is available with a simple installer:

http://www.postgresql.org/download/macosx

Designing the Model

Start Xcode and create a new project of type Cocoa Application. Name the project CarLot. Imagine that you own several used car lots. This application will enable you to keep track of the cars that you wish to sell. Better your staff at each lot can see and update this information. When it is done, it will look like Figure 1.

Figure 1. Completed Application

In the new project add a new group, name it Models. Within it add a new file of type Data Model, name it CarLotModel.xcdatamodel. We won’t be adding any existing classes as entities, so click Finish.

Now we need to uncheck the target membership, as shown in Figure 2. The data model will be used by the BaseTen Assistant to create a database schema, but will not be compiled into the project.

Figure 2. Removing the data model from the current target

Open CarLotModel.xcdatamodel. At the bottom of the Entity table view, click the + button to create a new entity. Name the entity Car.

With the Car entity selected, choose Add Attribute in the pop-up at the bottom of the Properties table view. Add six attributes and give them the following names and types. Finally save the model.

Name Type
condition Integer 16
datePurchased Date
makeModel String
onSpecial Boolean
photo Binary data
price Decimal

Figure 3 shows what it looks like in the modeller.

Figure 3. Completed Model

Building the Database Schema

Launch the Terminal utility and create a new PostgreSQL database named cars. See the PostgreSQL manual for more information on how to do this. If the PostgreSQL bin folder is not in your user path you will need to navigate there manually:

cd /Library/PostgreSQL/8.3/bin

./createuser -S -D -r -E -U postgres -P carlot

Enter a password for the new role. Enter it again to confirm. Now enter your postgres password to create the new user. Now create the new database:

./createdb -E UTF-8 -O carlot -U postgres cars

Enter the postgres password.

Start the BaseTen Assistant. Connect to the PostgreSQL server, specifying the cars database and the carlot user name and password. Click Import Model on the toolbar, or press ⌘O. Choose the CarLotModel.xcdatamodel you recently created. The import sheet will be displayed, as shown in Figure 4.

Figure 4. BaseTen Assistant’s Import Sheet

Check the Car box in the Tables table view. Now press Import Model. Because this is a new database the BaseTen schema, required by the framework, needs to be installed. Click on Install when prompted to install the BaseTen schema. The imported schema should look like Figure 5.

Figure 5. The Imported Car Schema

Add Frameworks

Return to Xcode. Expand the Frameworks group, then select the Linked Frameworks group within it. Now choose Add → Existing Frameworks from the context menu. Navigate to /Library/Frameworks/ and add BaseTen.framework and BaseTenAppKit.framework.

Add a Copy Files Build Phase

BaseTen and BaseTenAppKit have been set up so that they are expected to be found inside an application bundle. To make sure the frameworks get copied inside your application, expand the Targets group and the CarLot target inside it. Select CarLot and choose Add → New Build Phase → New Copy Files Build Phase from the context menu. An info window for the build phase will open. Select Frameworks as the target, leave the path field empty and close the window. Now drag BaseTen.framework and BaseTenAppKit.framework from Linked Frameworks onto the new build phase. You can also rename it by choosing Rename from the context menu.

Figure 6. Build phases

Interface

Open MainMenu.xib. Since you added BaseTenAppKit to your project, Interface Builder should automatically load the BaseTen plug-in. You can check this from the Plug-ins pane of Interface Builder preferences.

Look for BXDatabaseContext and BXSynchronizedArrayController in the Library palette, Figure 7 shows what they look like. Drag one of each into the MainMenu.xib window.

Figure 7. Interface Builder Library Palette showing the new BaseTen objects.

Select the Database Context. In the Attributes Inspector, set the Database URI to pgsql://carlot@localhost/cars/. Also check Autocommits (Figure 8).

Figure 8. Configuring BXDatabaseContext

Select the Synchronized Array Controller. Hold control and drag a connection from the databaseContext outlet to the Database Context object in the MainMenu.xib window (Figure 9).

Note: Under some circumstances the outlets and actions won't show up when the Interface Builder plug-in has been loaded for the first time. If this happens, save and close your MainMenu.xib and open it again. Also relaunching Interface Builder has solved the issue.

Figure 9. Configuring BXSynchronizedArrayController connetions.

Switch to the Attributes Inspector, set the Table Name to Car. Check the Fetch On Connect option. In the MainMenu.xib window rename the Synchronized Array Controller to Cars, this makes it easier to refer to later on. See Figure 10.

Figure 10. Configuring BXSynchronisedArrayController attributes

Create and Configure Views

Open the NSWindow object. Drag out an NSTableView from the Library and drop it in the window. In the Attributes Inspector, give the table three columns. Name them Make/Model, Price, and Special. Drop a number formatter on the Price column. Select the formatter (represented by a little circle in the column), and configure it to show currency. Use the 10.4+ formatter, and set the style to Currency. Also, check the boxes Generate Decimal Numbers and Always Shows Decimal (Figure 11).

The third column will be populated by check boxes, so drop a check box cell on the third column. Select the cell, and clear its title.

Below the table view, drop on the window an NSDatePicker, two NSButtons, an NSImageView (Image Well) and an NSLevelIndicator. Put label text fields next to the date picker and the level indicator. The buttons should be labelled New and Delete.

The labels should be Date Purchased: and Condition:. In the Attributes Inspector of the NSLevelIndicator, set its min to 0 and its max to 5. Set its style to Rating mode (to get the stars). Also, make the level indicator editable. See Figure 12.

Make the NSImageView editable by using the Attributes Inspector.

Figure 11. Configure the Number Formatter
Figure 12. Attributes of the NSLevelIndicator

Select the date picker, the image view, the two labels, and the level indicator. Go to the Layout menu and select the Embed Objects In → Box menu item.

Connections and Bindings

Now, you are going to do a bunch of bindings. I will walk you through it step by step; Figure 13 is a diagram of the bindings that you are going to create between your views and the array controller.

Figure 13. Summary of the Bindings

Bind the value of each column:

Binding Bind to Controller Key Key Path
value of Col 0 Cars arrangedObjects makeModel
value of Col 1 Cars arrangedObjects price
value of Col 2 Cars arrangedObjects onSpecial

Make the New button trigger the add: method of the Cars object, and make the Delete button trigger the remove: method of the Cars object.

Bind the value of the controls to the selection of the Cars:

Binding Bind to Controller Key Key Path
value of date picker Cars selection datePurchased
enabled of Delete button Cars canRemove
value of level indicator Cars selection condition

Bind the Data (not Value) of the image view to Cars. Choose the controller key selection and the key path photo. Also, check the box that says Conditionally Sets Editable (Figure 14).

Figure 14. Image View Binding

Bind the Title With Pattern of the box to Cars. Set the Controller Key to selection. Set the Model Key Path to makeModel. Set the Display Pattern to Details for %{title1}@ . Set the No Selection Placeholder to <No selection>. Set the Null Placeholder to <No make/model>. See Figure 15.

Finally make the text of the first two columns appear in bold if the car is on special. Bind the Font Bold binding to Car’s arrangedObjects.onSpecial (Figure 16).

Figure 15. Box Binding
Figure 16. Specials Appear in Bold.

That’s it. Make sure MainMenu.xib is saved, then build and run the application.

Testing

New cars can be added by clicking the Add button. The make/model, pric and on special information can be edited in the table view. A picture can be dragged to the image well. Add the details for a few cars.

From the Termial application connect to the database with psql -U carlot cars. Type a simple query:

select "makeModel", "price", "onSpecial", from "Car";

Press return. PostgreSQL will output the data you entered in the CarLot application.

Try updating the data with a query such as:

update "Car" set "price" = "price" - 1000, "onSpecial" = true;

All cars will be reduced in price by £1000 and marked as on special.

Notice how the table view in CarLot application automatically updates when you do this.