Home > 2010 Winter DPS913 > DPS913 APD601 Lab 2 guidance

DPS913 APD601 Lab 2 guidance

February 1, 2010 Leave a comment Go to comments

This post has information that will guide you through your work on Lab 2.

.

Comments about the design

We suggest that you keep your design simple. Although you may consider creating a “bus route” class, with properties for the route code, the route name, the ticket price, and the number of available seats, don’t do it yet.

Instead, use simple arrays. You really need only two arrays: One for the ticket prices, and one for the available seats. Each array will have four elements – one for each bus route. We’ll also use a segmented control, with four segments, for the four bus routes.

We will logically associate the positions of the segmented control and the array elements ourselves. Our design will be very static, so it’s safe to do it. This simple design will allow you to learn the concepts you have to learn, and still get lots of practice creating a Cocoa Touch application.

The following table shows the logical associations that WE will maintain ourselves:

Bus route Segmented control segment Array for
ticket prices
Array for
available seats
Toronto to
Barrie
0 – BAR 29.80 38
Toronto to
London
1 – LON 41.35 38
Toronto to
Montreal
2 – MTL 106.40 38
Toronto to
Sault Ste. Marie
3 – SSM 150.70 38

When the user wants to select the “Toronto to Barrie” bus route, they will tap the BAR segment. That’s segment 0 (zero).

This number becomes our element number for the arrays: Element 0 (zero) of the ticket prices array has the Barrie ticket price in it, and, element 0 (zero) of the available seats array has the number of seats available on the Barrie bus route.

So, the segmented control’s selectedSegmentIndex property will drive the operation of the program.

Only the available seats array has values that will change during the use of our program. Therefore, you will use an NSMutableArray. The ticket prices array can be an NSArray.

.

Getting started

In my working example, I used a “View-based Application” template, and suggest that you do the same.

To get started, you should consider creating the user interface. For the text labels, enter descriptive text for now. (As you write code, you can always set the label’s text property with status information and results.)

As you have learned, the UIPickerView control requires a data source and a delegate. The purpose of the picker will be to enable the user to select the number of tickets to be sold for the selected bus route. Therefore, in the suggested design, you should create a (mutable) array that will act as the picker’s data source. This will enable you to 1) generate an array with the number of elements that matches a bus route’s available seats, and 2) format the picker’s visible text entries in the way that you want. You can then re-generate the array when the user picks a different route, or when they “buy” tickets.

The view controller class can be used as the data source and delegate. Therefore, it will have the methods that enable the picker to get its visible data and provide selection notifications. It will also have methods to handle the button tap, the segmented control tap, and maybe a few other convenience methods.

So, here’s a list of the objects that your project should have:

  • Segmented control (UI)
  • Picker view control (UI)
  • Labels for status and info (UI)
  • A button control to “buy” tickets (UI)
  • Array, 4 elements, for the ticket prices (on each bus route)
  • Array, mutable, 4 elements, for the number of available seats (on each bus route)
  • Array, mutable, as a picker data source, with a variable number of elements
  • Methods for the data source and delegate
  • Methods for other user operations

The arrays can be declared properties, which will simplify your syntax.

.

Declaring methods for the picker

We learned the following during a recent lecture section: The view controller will be the data source and delegate for the picker. What methods do we need to implement? The UIPickerView documentation tells us that the delegate must adopt the UIPickerViewDelegate protocol. When we look at the UIPickerViewDelegate documentation, we see that the following must be implemented:

  • pickerView:titleForRow:forComponent:

There is one optional method that we must implement:

  • pickerView:didSelectRow:inComponent:

The documentation also says that the data source must adopt the UIPickerViewDataSource protocol. When we look at the UIPickerViewDataSource documentation, we see that the following must be implemented:

  • numberOfComponentsInPickerView:
  • pickerView:numberOfRowsInComponent:

Reminder: When you implement methods from a superclass or a delegate (or a data source), you do not have to declare the method signatures in the interface (.h). You simply implement the method in the implementation (.m). The Xcode editor will help you with the method signature: Type a dash, a space, a few letters from the method name, and press Esc to choose from the pop-up list of members.

.

Other methods

We will need methods that handle the segmented control tap and the button tap.

Also, it would be a good idea to have a method that would rebuild the data source for the picker. Both of the methods just mentioned (segmented control tap, and button tap) would require that the data source be rebuilt/regenerated. Therefore, create a method to do this, and call it from the two user-action methods.

.

Next – make the user interface work

Now that we have the planning done, it’s time to do the programming. We suggest that you complete the user interface by making it work.

.

Implement the segmented control tap

Next, you could implement the pickerView:didSelectRow:inComponent: method, but the picker doesn’t show up in the user interface. It won’t show up until we create the data source.

Before creating the data source, let’s create the arrays for the ticket prices and the available seats. Where does this code go? We will put the code in the view controller. Where exactly? Well, we want the data to be available just before the view loads. Why? The view needs access to the data, so that it can (among other tasks) build the picker. Therefore, implement the superclass’s awakeFromNib: method. (See the NSObject documentation for its signature.) The awakeFromNib: method will run once in our application. (Remember that when implementing a superclass method, one of the first things you do is call the superclass’s method of the same name. In our case, it’s: [super awakeFromNib];)

Then, create the arrays. If you’ve used declared properties for the arrays, you can use syntax like “self.ticketPrices = …” and one of the factory/convenience methods to build the array. Tip: use [NSNumber numberWthFloat:…] to create a float wrapped in an object that can go into an array element. (There’s also a numberWithInt: method; see the NSNumber documentation for details.) Remember: When creating an array with a factory/connvenience method, the last element must be nil.

At this point, make sure the arrays get built by using the NSLog function (or reporting to the user interface).

Now, you can create the data source (array) for the number of available seats for the bus route. Before you do, decide what segment will be selected when the program starts. That will determine the selected bus route, and the ticket price. You’ll need that information, so that you can build the data source in a way that matches the example shown in the Lab 2 specifications.

Where do you create the data source array? In the awakeFromNib: method? No. As stated above, you’ll want to rebuild the data source whenever the segmented control selection changes, and when the “Buy” button is tapped. Therefore, it needs to go somewhere else.

The suggested approach is to create a method (maybe called buildThePicker) that does this job. Then, it can be called any time it is needed (including the first load/launch of the app). The method should have an argument, so that the selected bus route value can be passed in. Then, the method will create the array, by looking in the other arrays (for the ticket price and available seats). Ideally, as noted earlier, if you make this array a declared property, it becomes very easy to rebuild and make available (e.g. “self.pickerData = …”).

Tip: Include “0” (zero) in the picker’s data source array. That way, your index matches the visible row value. This provides a good default/initial value for the number of tickets to be purchased when a route selection changes. It also enables you to clearly show that there are zero tickets available when all have been sold on a bus route.

.

Making all the moving parts work right

At this point, you should have all the building blocks in place.

We know that selecting a different segment should result in a picker data source rebuild. If the picker is at a non-zero row, what should the desired behaviour be? We suggest that you spin back the picker to row zero. There’s a picker method for that: selectRow:inComponent:animated:

Similarly, after a “purchase” is completed, what should happen to the picker? Should its selected row stay at the row for the number of tickets purchased? We suggest that again, you spin it back to row zero.

Good luck!

.


Advertisements
Categories: 2010 Winter DPS913
  1. No comments yet.
  1. February 16, 2010 at 8:13 pm

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: