1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu Lập trình iPhone part 7 pptx

46 343 0
Tài liệu được quét OCR, nội dung có thể không chính xác
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Tài liệu Lập trình iPhone part 7 pptx
Trường học Dai Hoc Bach Khoa Ha Noi
Chuyên ngành iPhone Programming
Thể loại Giáo trình
Năm xuất bản 2023
Thành phố Hà Nội
Định dạng
Số trang 46
Dung lượng 1,59 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The first content view we'll build will have a date picker, which is the easiest type of picker to implement see Figure 7-2.. We'll see how to use the datasource and delegate to provide

Trang 1

Tab Bars

and Pickers

n the last chapter, you built your first multiview application In this chapter,

you're going to build a full tab bar application with five different tabs and five

different content views Building this application is going to reinforce a lot of

what you learned in the last chapter, but you’re too smart to spend a whole

chapter doing stuff you already sorta know how to do, so we're going to use

those five content views to show you how to use a type of iPhone control that

we have not covered yet The control is called the picker view, although it’s

usually just called the picker

„ii ATKT >

Figure 7-1 A picker in the

Clock application

You may not be familiar with the name, but

you've almost certainly used a picker if you've owned an iPhone for more than, say, 10 min- utes Pickers are the controls with dials that spin You use them to input dates in the Cal- endar application or to set a timer in the Clock application (see Figure 7-1)

Pickers are rather more complex than the iPhone controls you've seen so far, and as such, they deserve a little more attention Pickers can

be configured to display one dial or many By

default, pickers display lists of text, but they can also be made to display images

Trang 2

The Pickers Application

This chapter's application, Pickers, will feature a tab bar As you build Pickers, you'll change

the default tab bar so it has five tabs, add an icon to each of the tab bar items, and then cre- ate a series of content views and connect each to a tab

The first content view we'll build will have a date picker, which is the easiest type of picker

to implement (see Figure 7-2) The view will also have a button that, when tapped, will dis- play an alert that displays the date that was picked

The second tab will feature a picker with a single list of values (see Figure 7-3) This picker is

a little bit more work to implement than a date picker You'll learn how to specify the values

to be displayed in the picker by using a delegate and a datasource

In the third tab, we’re going to create a picker with two separate wheels The technical term

for each of these wheels is a picker component, so here, we are creating a picker with two components We'll see how to use the datasource and delegate to provide two independent lists of data to the picker (see Figure 7-4) Each of this picker’s components can be changed without impacting the other one

In the fourth content view, we're going to build another picker with two components But this

time, the values displayed in the component on the right are going to change based on the value selected in the component on the left In our example, we're going to display a list of states in the left component and a list of that state’s ZIP codes in the right component (see Figure 7-5)

co LoL

Figure 7-2 The first tab will Figure 7-3 A picker display- Figure 7-4 A two-

showa date picker ing a single list of values component picker

Trang 3

And last, but most certainly not least, we're going to have

a little fun with the fifth content view We're going to see how

to add image data to a picker, and we're going to do it by writ-

ing alittle game that uses a picker with five components In several places in Apple’s documentation, the picker’s appear- ance is described as looking a bit like a slot machine Well, then,

what could be more fitting than writing a little slot machine

game (see Figure 7-6)? For this picker, the user won't be able

to manually change the values of the components but will be able to select the Spin button to make the five wheels will spin

to a new, randomly selected value If three copies of the same image appear in a row, the user wins

atl > 8:56 PM =

ee

z

one component is dependent

BARÍ|BAR|BARIE

nent, the right component

changes to a list of ZIP codes

Delegates and Datasources

Before we dive in and start building our application, let’s look

at why pickers are so much more complex than the other

controls you've used so far It’s not just a matter of there being

fact, the picker actually has very few attributes that are con- ponent picker Note that we

figurable in Interface Builder With the exception of the date ; ; } ; iPhone as a tiny casino picker, you can’t use a picker by just grabbing one in Interface

Builder, dropping it on your content view, and configuring it

You have to also provide it with both a picker delegate and

a picker datasource

By this point, you should be comfortable using delegates We've already used application delegates and action sheet delegates, and the basic idea is the same here The picker defers several jobs to its delegate The most important of these is the task of determining what to actually draw for each of the rows in each of its components The picker asks the delegate for either a string or a view that will be drawn at a given spot on a given component

Trang 4

In addition to the delegate, pickers have to have a datasource The datasource works similarly

to the delegate, in that its methods are called at certain, prespecified times Picker datasource methods are used by the picker to get the number of components and the number of rows in each component Without a datasource and a delegate specified, pickers cannot do their job and, in fact, won't even be drawn

It's very common for the datasource and the delegate to be the same object, and just as common for that object to be the view controller for the picker’s enclosing view, which is the approach we'll be using in this application The view controllers for each content pane will

be the datasource and the delegate for their picker

Let's fire up Xcode and get to it

Setting Up the Tab Bar Framework

Although Xcode does provide a template for tab bar applications, we’re going to build ours from scratch It’s not much extra work, and it’s good practice So, create a new project, select- ing the Window-Based Application template again When prompted for a name, type Pickers

We're going to walk you through the building of the whole application, but if, at any step of

the way, you feel like challenging yourself by moving ahead of us, by all means, go ahead If you get stumped, you can always come back If you don't feel like skipping ahead, that’s just fine We'd love the company

Creating the Files

In the last chapter, we created a root view controller We'll be doing that again this time, but

we won't need to create a class for it, because Apple provides a very good one for managing

tab bar views, so we're just going to use an instance of UITabBarControl ler for our root controller We will create that instance in Interface Builder in a few minutes

Trang 5

We need to create five new classes in Xcode: the five view controllers that the root controller

will swap in and out

Expand the Classes and Resources folders in the Groups & Files pane Next, single-click the Classes folder, and press 88N or select New File from the File menu

Select Cocoa Touch Classes in the left pane of the new file assistant, and then select the icon for UlViewController subclass, and click Next Name the first one DatePickerViewController.m, making sure to check Also create “DatePickerViewController.h’

Repeat four more times, using the names SingleComponentPickerViewController.m,

DoubleComponentPickerViewController.m, DependentComponentPickerViewController.m, and CustomPickerViewController.m

Next, single-click the Resources folder, and press 88N or select New File from the

File menu again This time, you want to select User Interfaces in the left pane of the new file assistant, and then click the View X/B icon We need five nibs, one for each content view Call the first one you create DatePickerView.xib Then create four more: SingleComponent- PickerView.xib, DoubleComponentPickerView.xib, DependentComponentPickerView.xib, and CustomPickerView.xib

Setting Up the Content View Nibs

Double-click DatePickerView.xib to open the file in Interface Builder We're not actually

going to build our content views yet We're just going to wire up the skeleton of our tab view application now so that the basic application works We have to make sure that each

of the nib files is pointing to the right File’s Owner icon, which needs to be the correspond- ing UIViewControl ler subclass For DatePickerView.xib, the controller class needs to be DatePickerViewControl ler Single-click File’s Owner, and then press 84 to bring up the identity inspector Change the class to DatePickerViewController

Now, control-drag from the Files Owner icon to the View icon, and select the view outlet Finally, single-click the View icon, and press 383 to bring up the size inspector Change the height of the view to 411 pixels, which is the amount of space remaining after you take out the status bar and the tab bar Save this nib, and close it

Repeat all those same steps with each of the four remaining nib files, making File’s Owner

point to the corresponding view controller Make sure you save each nib file as you finish up, and when you’re done with all five, go back to Xcode

Trang 6

Adding the Root View Controller

We're going to create our root view controller, which will be an instance of

UITabBarControl ler, in Interface Builder Before we can do that, however, we should declare an outlet for it Single-click the PickersAppDelegate.h class, and add the following code to it:

#1mport <UTK1t/UTK1t.h>

@class PickersViewController;

@interface PickersAppDelegate : NSObject <UIApplicationDelegate> {

IBOutlet UIWindow *window;

IBOutlet UITabBarController *rootController;

- (void)applicationDidFinishLaunching: CUIApplication *)application {

// Override point for customization after app launch

[window addSubview: rootController.view] ;

Trang 7

There shouldn't be anything there that’s a surprise

to you It’s pretty much the same thing we did in the

last chapter, except that we're not using a controller

class provided by Apple; instead, we're using one

we wrote ourselves Make sure you save both files

Tab bars use icons to represent each of the tabs,

so we should also add the icons we're going to use

before heading over to Interface Builder You can

find some suitable icons in the project archive that

accompanies this book in the 07 Pickers/Tab Bar

Icons/ folder The icons should be 24 by 24 pixels

and saved in png format The icon file should have

a transparent background Generally, medium grey

icons look the best on a tab bar Don’t worry about

trying to match the appearance of the tab bar Just

as it does with the application icon, the iPhone is

going to take your image and make it look just right

You should be comfortable adding resources to your

project by this point, so go ahead and add the five

icons we've provided by dragging them from the

finder to the Resources folder of your Xcode proj-

ect or selecing Add to Project from the Project

menu

Once you've added the icons, double-click

MainWindow.xib to open the file in Interface Builder

Drag a Tab Bar Controller from the library (see

Figure 7-7) over to the nib’s main window Be sure

you drag to the window labeled MainWindow.xib

and not to the window labeled Window, which will

not accept the drag, so you'll know when you get

it right

Once you drop the tab bar controller onto your nibs

main window, a new window will appear that looks

like Figure 7-8 This tab bar controller will be our

root view controller As a reminder, the root view

controller controls the very first view that the user

will see when your program runs

manages navigation through a hierarchy of yw

Tab Bar Controller - A controller that manages a set of view controllers that represent tab bar items

Image Picker Controller —- A controller that manages views for choosing and taking pictures

Trang 8

Single-click the Tab Bar Controller icon in your nibs main

window, and press 361 to bring up the attributes inspec-

tor for it The attributes inspector for a tab bar controller

will look like Figure 7-9

The part that we're interested in is the top section, which

is labeled View Controllers When all is said and done,

we'll end up with one view controller for each of our tab

controller's tabs Take a look back at Figure 7-2 As you

can see, our program features five tabs, one for each of

our five subviews—five subviews, five view controllers

Turn your attention back to the attributes inspector for

the tab bar controller We need to change our tab bar

controller so it has five tabs instead of two Click the but-

ton with the plus sign on it three times to create a total

of five controllers The attributes inspector will show

five items, and if you look over at the Tab View Controller

window, you'll see that it now has five buttons instead

of two

Click the tab bar at the bottom of the Tab Bar Controller

window Be sure you click the leftmost tab This should

select the controller that corresponds to the leftmost

tab, and the inspector should change to look like

Figure 7-10

Here’s where we associate each tab’s view controller

with the appropriate nib This leftmost tab will launch

the first of our five subviews Leave the Title field blank

and specify a NIB Name of DatePickerView Do not

include the xib extension

While you are here, press 384 This will bring up the

identity inspector for the view controller associated

with the leftmost tab Change the class to DatePicker-

ViewController, and press return or tab to set it

Status Bar ( Gray 4

Bottom Bar ( Tab Bar kê)

Trang 9

Type 31 to return to the attributes inspector Click the

first tab in the tab bar, and click it again in the same ————

spot This should cause the inspector to change again, min

By clicking the tab bar again in the same spot, we’ve a —

ated with the tab bar item to the tab bar item itself In Tag 0

other words, the first click selected the first of the five M Enabled

subview’s view controllers The second click selects the

tab bar item itself so that we can set its title and icon

This is where we can specify the tab bar item's icon Figure 7-11 The tab bar item

Image combo box; and select the clockicon.png image

If you are using your own set of icons, select one of the

.png files you provided instead For the rest of this chapter, we'll discuss the resources we provided Make adjustments for your own media, as necessary

If you look over at the Tab Bar Controller window, you'll see that the leftmost tab bar item now reads Date and has a picture of a clock on it We now need to repeat this process for the other four tab bar items

The second view controller should be given a title of Single and a nib name of

SingleComponentPickerView In the identity inspector, its class should be changed

to SingleCcomponentPickerViewController The second tab bar item should be given a title of Single, and it should use the icon called singleicon.png

The third view controller should be given a title of Double and a nib name of

DoubleComponentPickerView Its class should be changed to DoubleComponentPickerView- Controller The third tab bar item should be assigned a title of Double, and it should be assigned the image called doubleicon.png

The fourth view controller should be assigned a title of Dependent and a nib name of

DependentComponentPickerView Its class should be changed to DependentComponentPicker- ViewController The fourth tab bar item gets a title of Dependent and should be assigned the icon image dependenticon.png

The fifth and last view controller should be assigned a title of Custom, a nib name of Custom- PickerView |ts class should be changed to CustomPickerViewController The last tab bar item also gets a title of Custom and the toolicon.png icon

Trang 10

All that we have left to do in this nib file is to control-drag from the Pickers App Delegate icon

to the Tab Bar Controller icon, selecting the rootController outlet Save your nib, and go back

to Xcode

At this point, the tab bar and the content views should all be hooked up and working Com-

pile and run, and your application should launch with a toolbar that functions; clicking a tab

should select it There’s nothing in the content views now, so the changes won't be very

dramatic But if everything went okay, the basic framework for your multiview application is now set up and working, and we can start designing the individual content views

working, you'll see the content of the different views change as you select different tabs

Implementing the Date Picker

To implement the date picker, we'll need a single outlet and a single action The outlet

will be used to grab the value from the date picker The action will be triggered by a but-

ton and will throw up an alert to show the date value pulled from the picker Single-click DatePickerViewController.h, and add the following code:

#import <UIKit/UIKit.h>

@interface DatePickerViewController : UIViewController {

}

- CIBAction) buttonPressed;

@end

Save this file, and double-click DatePickerView.xib to open the content view for this first tab

in Interface Builder The first thing we need is a date picker, so look for Date Picker in the

library (see Figure 7-12), and drag one over to the View window If the View window is not open, open it by double-clicking the View icon in the nib’s main window

Trang 11

wwe wee

to a target object when Return is tapped

Picker View — Displays a spinning-wheel

or slot-machine motif of values

Date Picker — Displays multiple rotating

wheels to allow users to select dates and ®

times

Library - Cocoa Touch Plugin — Inputs & Values

| 1 2 | segments, each of which functions as a

Place the date picker right at the top of the view

It should take up the entire width of your content

view and a good portion of the height Don’t use

the blue guidelines for the picker; it’s designed

to fit snugly against the edges of the view (see

Figure 7-13)

Single-click the date picker if it’s not already selected,

and press 361 to bring up the attributes inspector As

you can see (in Figure 7-14), a number of attributes can

be configured for a date picker You won't get off this

easy with the rest of the pickers, so enjoy it while you

can We're going to leave most of the values at their

defaults, though you should feel free to play with the

options when we're done to see what they do The one

thing we are going to do is limit the range of the picker

to reasonable dates Change the Minimum date value to

1/1/1900, and change the Maximum to 12/31/2200

Next, grab a Round Rect Button from the library, and

place it below the date picker Double-click it, and give

it a title of Select, and press 382 to switch to the con-

nections inspector Drag from the circle next to the

Touch Up Inside event over to the File’s Owner icon, and

connect to the buttonPressed action Then control-drag

from the File’s Owner icon back to the date picker, and

select the datePicker outlet Save, close the nib, and go

Mw Clear Context Before Drawing

Trang 12

Now we just need to implement DatePickerViewControl ler, so click

DatePickerViewController.m, and add the following code:

#import "DatePickerViewController.h"

@implementation DatePickerViewController

@synthesize datePicker;

bundle: C(NSBundle *)nibBundleOrNil {

if Cself = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNi1]) {

NSDate *selected = [datePicker date];

NSString *message = [[NSString alloc] initWithFormat:

@"The date and time you selected is: %@", selected];

UIAlertView “alert = [[UIAlertView alloc]

initWithTitle:@"Date and Time Selected"

message :message delegate:nil cancelButtonTitle:@"Yes, I did."

NSDate *now = [[NSDate alloc] init];

[datePicker setDate:now animated: YES];

[now release];

(BOOL) shouldAutorotateToInterfaceOrientation:

(UIInterfaceOrientation)interfaceOrientation {

// Return YES for supported orientations

(void) didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Releases the view if it doesn't have a superview

// Release anything that's not essential, such as cached data

Trang 13

In vi ewDidLoad, we created a new NSDate object An NSDate object created this way will hold the current date and time We then set datePicker to that date, which ensures that

every time this view loads, the picker will reset to the current date and time

Go ahead and build and run, make sure your date picker checks out If everything went OK,

your application should look like Figure 7-2 when it runs If you click the Select button, an alert sheet will pop up telling you the date and time currently selected in the date picker Though the date picker does not allow you to specify seconds or a time zone, the alert that displays the selected date and time displays both seconds and a time zone offset We could have added a formatter to simplify the string displayed in the alert, but isn’t this chapter long enough already?

Implementing the Single Component Picker

Well, date pickers are easy enough, but let’s look at using pickers that let the user select from

a list of values In this example, we're going to create an NSArray to hold the values we want

to display in the picker Pickers don’t hold any data themselves Instead, they call methods

on their datasource and delegate to get the data they need to display The picker doesn’t

really care where the underlying data is It asks for the data when it needs it, and the data-

source and delegate work together to supply that data As a result, the data could be coming from a Static list, as we'll do in this section, or could be loaded from a file or a URL, or even

made up or calculated on the fly

Declaring Outlets and Actions

As always, we need to make sure our outlets and actions are in place in our controller's header file before we start working in Interface Builder In Xcode, single-click

the delegate for its picker, so we need to make sure it conforms to the protocols for those two roles In addition, we'll need to declare an outlet and an action Add the following code:

#import <UIKit/UIKit.h>

@interface SingleComponentPickerViewController : UIViewController

<UIPickerViewDelegate, UIPickerViewDataSource> {

Trang 14

TBOutlet UIPickerView *singlePicker;

}

open the content view for the second tab in our tab

bar Bring over a Picker View from the library (see

Figure 7-15), and add it to your nib’s View window,

placing it snugly into the top of the view as you did

with the date picker view

Text View - Displays multiple lines of editable text and sends an action message

to a target object when Return is tapped Picker View — Displays a spinning-wheel

or slot-machine motif of values

a2 ese

After placing the picker, control-drag from File’s

Owner to the picker view, and select the singlePicker

outlet Next, single-click the picker if it’s not already

Segmented Control - Displays multiple

| segments, each of which functions as a discrete button

selected, and press 862 to bring up the connections Figure 7-15 The Picker View in the

the picker view, you'll see that the first two items are

DataSource and Delegate Drag from the circle next to DataSource to the File’s Owner icon Then drag again from the circle next to Delegate to the File’s Owner icon Now this picker knows that the instance of the Sing] eComponentPickerViewController class

is its datasource and delegate and will ask it to supply the data to be displayed In other words, when the picker needs information about the data it is going to display, it asks the Singl eComponentPickerViewControl ler instance that controls this view for that information

Drag a Round Rect Button to the view, double-click it, and give it a title of Select Press return

to commit the change In the connections inspector, drag from the circle next to Touch Up Inside to the File’s Owner icon, selecting the buttonPressed action Save the nib file, close it, and go back to Xcode

Trang 15

Implementing the Controller As Datasource and Delegate

To make our controller work properly as the picker’s datasource and delegate, we are going to have to implement a few methods that you've never seen before Single-click SingleComponentPickerViewController.m, and add the following code:

#import "SingleComponentPickerViewController.h"

@implementation SingleComponentPickerViewController

@synthesize singlePicker;

@synthesize pickerData;

bundle: C(NSBundle *)nibBundleOrNil {

NSString *selected = [pickerData objectAtIndex: row];

NSString *title = [[NSString alloc] initWithFormat:

@"You selected %@!", selected];

UIAlertView “alert = [[UIAlertView alloc] initWithTitle:title

message:@"Thank you for choosing."

delegate:nil cancelButtonTitle:@"You're Welcome"

NSArray “array = [[NSArray alloc] initWithObjects:@"Luke", @"Leia”,

@"Han", @"Chewbacca", @"Artoo", @"Threepio", @"Lando", nil]; self.pickerData = array;

[array release];

}

- (BOOL) shouldAutorotateToInterfaceOrientation:

(UIInterfaceOrientation)interfaceOrientation {

// Return YES for supported orientations

return CinterfaceOrientation == UIInterfaceOrientationPortrait);

Trang 16

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Releases the view if it doesn't have a superview

// Release anything that's not essential, such as cached data

#pragma mark Picker Data Source Methods

{

return 1;

}

- (NSInteger)pickerView: (CUIPickerView *)pickerView

{

return [pickerData count];

}

#pragma mark Picker Delegate Methods

- (NSString *)pickerView: (UIPickerView *)pickerView

titl eForRow: (NSInteger) row

forComponent: (NSInteger) component

return [pickerData objectAtIndex: row];

}

@end

The first two methods should be familiar to you by now The buttonPressed method is nearly identical to the one we used with the date picker Unlike the date picker, a regular picker can’t tell us what data it holds, because it doesn’t maintain the data It hands that job

off to the delegate and datasource Instead, we have to ask the picker which row is selected

and then grab the corresponding data from our pickerData array

Here is how we ask it for the selected row:

Trang 17

Notice that we had to specify which component we want to know about We only have one component in this picker, so we simply pass in 0, which is the index of the first component

CAUTION

Did you notice that there is no asterisk between NSTnteger and row Although, on the iPhone, the

prefix”NS” usually indicates an Objective-C class from the Foundation framework, this is one of the

exceptions to that general rule NSTInteger is always defined as an integer datatype, either an int ora long We useNSInteger rather than int or long, because when we use NSInteger, the compiler automatically chooses whichever size is best for the platform for which we are compiling It will create a 32-bit int when compiling for a 32-bit processor and a longer 64-bit 1ong when compiling for

a 64-bit architecture At present, there is no 64-bit iPhone, but who knows? Someday in the future, there

may be You might also write classes for your iPhone applications that you'll later want to recycle and use

in Cocoa applications for Mac 0S X, which already does run on both 32- and 64-bit machines

making it much harder on ourselves if we need to update this list or if we want to have our

application translated into other languages But this approach is the quickest and easiest way to get data into an array for demonstration purposes Even though you won't usually create your arrays like this, you will almost always cache the data you are using into an array here in the vi ewDidLoad method so that you're not constantly going to disk or to the net-

work every time the picker asks you for data

TIP

If you're not supposed to create arrays from lists of objects in your code as we just did in vi ewDi dLoad, how should you do it? Embed the lists in property list files, and add those files to the Resources folder of your project Property list files can be changed without recompiling your source code, which means no risk of introducing new bugs when you do so You can also provide different versions of the list for differ- ent languages, as you'll see in the chapter on localizing your application, Chapter 17 Property lists can

be created using the Property List Editor application located at /Developer/Applications/Utilities/Property List Editor.app, or right in Xcode, which supports the editing of property lists in the editor pane Both

NSArray and NSDictionary offer a method called ini twithContentsOfFi le: to allow you

to initialize instances from a property file, something we'll do in this chapter when implementing the Dependent tab

Trang 18

At the bottom of the file, we get into the new methods required to implement the picker The first two methods after deal loc are from the UIPickerViewDataSource protocol, and they are both required for all pickers (except date pickers) Here's the first one:

to have multiple pickers being controlled by the same datasource In our case, we know that

we have only one picker, so we can safely ignore this argument because we already know which picker is calling us

The second datasource method is used by the picker to ask how many rows of data there are

for a given component:

numberOfRowsTnComponent : (NSInteger) component

return [pickerData count];

Once again, we are told which picker view is asking, and which component that picker is asking about Since we know that we have only one picker and one component, we don't bother with either of the arguments and simply return the count of objects from our data

array

After the two datasource methods, we implement one delegate method Unlike the data- source methods, all of the delegate methods are optional The term “optional” is a bit deceiving because you do have to implement at least one delegate method You will usually implement the method that we are implementing here As you'll see when we get to the custom picker, if you want to display something other than text in the picker, you have to implement a different method instead

- (NSString *)pickerView: CUIPickerView *)pickerView

titleForRow: (NSInteger) row

Trang 19

PRAGMA WHAT?

Did you notice these lines of code from SingleComponentPicker ViewController.m?

#pragma mark -

#pragma mark Picker Data Source Methods

Any line of code that begins with #p ragma is technically a compiler directive, specifically, a pragmatic, or compiler-specific, directive that won't necessarily work with other compilers or in other environments If

the compiler doesn’t recognize the directive, it ignores it, though it may generate a warning In this case, the

#pragma directives are actually directives to the IDE, not the compiler, and they tell Xcode'’s editor to put

a break in the pop-up menu of methods and functions at the top of the editor pane as shown in the follow- ing screen shot The first one puts a divider line in the menu The second creates a bold entry

v ES Pickers 8 l SingleComponentPickerViewController.h & @implementation SingleComponentPickerViewController

¥ (iu Classes B ® -initWithNibName:bundle:

ệ (4 |) SingleComponentPickerViewController.m:57 + ¡AE 3u

R DatePickerViewCont 13 @synthesize singlePicker; © -numberOfComponentsinPickerView:

E baron 24 NSInteger row = [singlePicker selectedRowInComponent :6];

= “Png 25 NSString *selected = [pickerData objectAtIndex:row];

[S| cherry.png 27 UlAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:@"Thank you for choosing." delegate:nil [s| lemon.png cancelButtonTitle:@"You're Welcome" otherButtonTitles:nil];

|*\ doubleicon.png 33 NSArray *array = [[NSArray alloc] initWithObjects:@"Luke", @"Leia", @"Han", @"Chewbacca", @"Artoo",

[a Š ghi on xe @"Threepio", @"Lando", nil];

we simply ignore everything except the row argument and use that to return the appropri- ate item from our data array

Trang 20

Go ahead and compile and run again When the simulator comes up, switch to the second

tab—the one labeled Single—and check out your new custom picker, which should look like Figure 7-3

When you’re done reliving all those Star Wars memories, come on back to Xcode and we'll see how to implement a picker with two components If you feel up to a challenge, this next content view is actually a good one for you to attempt on your own You've already seen all the methods you'll need for this picker, so go ahead, take a crack at it We'll wait here You might want to start off with a good look at Figure 7-4, just to refresh your memory When you're done, read on, and you'll see how we tackled this problem

Implementing a Multicomponent Picker

The next content pane will have a picker with two components or wheels, and each wheel will be independent of the other wheel The left wheel will have a list of sandwich fillings, and the right wheel will have a selection of bread types As we mentioned a moment ago, we'll write the same datasource and delegate methods that we did for the single component

picker, we'll just have to write a little additional code in some of those methods to make sure we're returning the right value and row count for each component

Declaring Outlets and Actions

Single-click DoubleComponentPickerViewController.h, and add the following code:

- CIBAction) buttonPressed;

@end

Trang 21

As you can see, we start out by defining two constants that will represent the two compo- nents, which will make our code easier to read Components are assigned numbers, with the leftmost component being assigned zero, and increasing by one each move to the right Next, we conform our controller class to both the delegate and datasource protocols, and

we declare an outlet for the picker, as well as for two arrays to hold the data for our two picker components After declaring properties for each of our instance variables, we declare

a single action method for the button, just as we did in the last two context panes Save this, and double-click DoubleComponentPickerView.xib to open the nib file in Interface Builder

Building the View

Add a picker and a button to the View, and then make the necessary connections We're not going to walk you through it this time, but you can refer to the previous section if you need

a step-by-step guide, since the two applications are identical in terms of the nib file Here’s

a summary of what you need to do:

=™ Connect the doublePicker outlet on File’s Owner to the picker

™ Connect the DataSource and Delegate connections on the picker view to File’s Owner (use the connections inspector)

™ Connect the Touch Up Inside event of the button to the buttonPressed action on File’s Owner (use the connections inspector)

Make sure you save your nib and close it before you head back to Xcode Oh, and dog-ear this page (or use a bookmark, if you prefer) You'll be referring to it in a bit

Implementing the Controller

Single-click DoublecomponentPickerViewController.m, and add the following code:

#import “Doub leComponentP1ckerV1ewController.h”

G@synthesize doublePicker;

Gsynthesize fillingTypes;

@synthes1ze breadTypes;

1f (Cself = [super 1n1tW1thN1bName :n1bNameOrN1 Ì

Trang 22

NSString *bread = [breadTypes objectAtIndex: breadRow] ;

NSString *message = [[NSString alloc] initWithFormat:

@"Your %@ on %@ bread will be right up.", filling, bread];

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:

@"Thank you for your order"

delegate:nil cancelButtonTitle:@"Great!"

NSArray *breadArray = [[NSArray alloc] initWithObjects:@"White",

@"Whole Wheat", @"Rye", @"Sourdough", @"Seven Grain", nil]; self.breadTypes = breadArray;

[breadArray release];

NSArray *fillingArray = [[NSArray alloc] initWithObjects:@"Ham",

@"Turkey", @"Peanut Butter", @"Tuna Salad",

@"Chicken Salad", @"Roast Beef", @"Vegemite", nil];

self.fillingTypes = fillingArray;

[fillingArray release];

(BOOL) shouldAutorotateToInterfaceOrientation:

(UIInterfaceOrientation)interfaceOrientation {

// Return YES for supported orientations

return CinterfaceOrientation == UIInterfaceOrientationPortrait);

(void) didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Releases the view if it doesn't have a superview

// Release anything that's not essential, such as cached data

Trang 23

#pragma mark Picker Data Source Methods

{

return 2;

}

- (NSInteger)pickerView: (CUIPickerView *)pickerView

{

if (component == kBreadComponent)

return [self.breadTypes count];

return [self.fillingTypes count];

}

#pragma mark Picker Delegate Methods

- (NSString *)pickerView: (UIPickerView *)pickerView

titleForRow: (NSInteger) row

forComponent: (NSInteger) component

{

if (component == kBreadComponent)

return [self.breadTypes objectAtIndex: row];

return [self.fillingTypes objectAtIndex:row];

}

@end

The buttonPressed method is a little more involved this time, but there’s very little there

that’s new to you; we just have to specify which component we are talking about when we request the selected row using those constants we defined earlier, kBreadComponent and

You can see here that using the two constants instead of 0 and 1 makes our code consider-

ably more readable From this point on, the buttonPressed method is fundamentally the

same as the last one we wrote

Ngày đăng: 21/01/2014, 10:20