Recipe 10-9 Building a Custom Dismissible Alert View That Responds to User Taps @interface TappableOverlay : UIView Get This Recipe’s Code To get the code used for this recipe, go to htt
Trang 1411 Recipe: Tappable Overlays
// Start the activity indicator
[(UIActivityIndicatorView *)[self.overlay viewWithTag:202]
startAnimating];
// Call the finish method, on delay
[self performSelector:@selector(finish) withObject:nil
afterDelay:3.0f];
}
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 10 and open the project for this recipe.
Recipe: Tappable Overlays
Use custom overlays to present information as well as to establish modal sequences
Recipe 10-9 creates a custom class called TappableOverlay.When tapped, this view
removes itself from the screen.This behavior makes it particularly suitable for showing
information in a way normally reserved for the UIAlertViewclass
To use this class, create a view instance in Interface Builder Add as many subviews and
design elements as needed Use File > Read Class Files to import the TappableOverlay.h
header file.Then change the view class from UIViewtoTappableOverlayusing the
Iden-tity Inspector (Command-4) and save the project
To present the view, add it to the window just as Recipe 10-8 did
- (void) action: (id) sender
{
// Add the overlay
[self.view.window addSubview:self.overlay];
}
No further programming is needed.The view waits for a user tap and when one is
received, it removes itself from the window
Figure 10-8 shows a simple example of this kind of overlay; it displays “Tap to
Con-tinue.” It’s easy to see how you can extend this concept to show any kind of pertinent
information, creating a custom alternative to the UIAlertViewclass As with Recipe 10-8,
this example does not use any orientation awareness
Trang 2Figure 10-8 This simple overlay dismisses itself
on receiving a user touch.
Recipe 10-9 Building a Custom Dismissible Alert View That Responds to User Taps
@interface TappableOverlay : UIView
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 10 and open the project for this recipe.
Recipe: Orientable Scroll-Down Alerts
You can extend the modal concepts introduced in Recipe 10-8 to create a noninteractive
overlay that acts as a backdrop for a scroll-down alert In Recipe 10-10, that overlay hosts
a view with an embedded button as shown in Figure 10-9.This view is presented and
Trang 3413 Recipe: Orientable Scroll-Down Alerts
Figure 10-9 This modally presented message scrolls down into view and is dismissed by tapping
the OKAY button.
dismissed via a pair of simple UIViewanimation blocks; the OKAY button triggers the
dismiss:method that scrolls the view offscreen
The message view was created in Interface Builder as a standard UIView It’s added to the
overlay as a subview in the viewDidLoadmethod Rather than adding and removing the
overlay from the main window, as Recipe 10-8 did, this recipe uses the overlay’s alpha
property to hide and show itself
Unlike the previous two recipes, this recipe does pay attention to screen orientation It
adapts its size and presentation to match the current iPhone orientation It accomplishes
this in two ways First, it applies an affine transform to the overlay when the orientation
changes Second, it adjusts the overlay and message view frames before presentation,
matching the shape of the current window
Although this example scrolls in from the top of the screen, it’s trivial to adapt the
math to have it scroll in from the sides (use the x origin rather than the y origin) or
bot-tom (add 320 or 480 to the view height) Alternatively, you might center the view and
animate its size so that it pops rather than slides into view
Recipe 10-10 Creating an Orientable Scroll-Down Overlay
- (void) dismiss: (id) sender
Trang 4// Animate the message view away
[UIView beginAnimations:nil context:NULL];
// Hide the overlay
[self.overlay performSelector:@selector(setAlpha) withObject:nil
// Animate the message view into place
[UIView beginAnimations:nil context:NULL];
Trang 5415 Recipe: Using the Network Activity Indicator
Figure 10-10 The network activity indicator is controlled by a UIApplication property.
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 10 and open the project for this recipe.
Recipe: Using the Network Activity Indicator
When your application accesses the Internet from behind the scenes, it’s polite to let your
user know what’s going on Rather than create a full-screen alert, Cocoa Touch provides a
simple application property that controls a spinning network activity indicator in the
sta-tus bar Figure 10-10 shows this indicator in action, to the right of the WiFi indicator and
to the left of the current time display
Recipe 10-11 demonstrates how to access this property, doing little more than toggling
the indicator on or off In real-world use, you’ll likely perform your network activities on
a secondary thread Make sure you perform this property change on the main thread so
the GUI can properly update itself
Trang 6Figure 10-11 The segmented control in Recipe 10-12 updates the
applica-tion badge number.
Recipe 10-11 Accessing the Status Bar’s Network Activity Indicator
- (void) action: (id) sender
{
// Toggle the network activity indicator
UIApplication *app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible =
!app.networkActivityIndicatorVisible;
}
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 10 and open the project for this recipe.
Recipe: Badging Applications
If you’ve used the iPhone or iPod touch for any time, you’ve likely seen the small, red
badges that appear over applications on the home screen.These might indicate the
num-ber of missed phone calls or unread e-mails that have accumulated since the user last
opened Phone or Mail
To set an application badge from within the program itself, set the applicationIcon
➥ BadgeNumberproperty to an integer.To hide badges, set applicationIconBadgeNumber
to 0 (the number zero) Recipe 10-12 demonstrates how to read and set an application
badge It matches the value of its segmented control to the most recently used badge
number.When users change the segmented control setting, it updates the badge
accord-ingly Figure 10-11 shows this in action, displaying the interface within the application and
the badge number it generates
Recipe 10-12 Reading and Updating Application Badges
Trang 7417 Recipe: Simple Audio Alerts
}
- (void) viewDidLoad
{
// Create the segment control for selecting the badge number
UISegmentedControl *seg = [[UISegmentedControl alloc]
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 10 and open the project for this recipe.
Recipe: Simple Audio Alerts
Audio alerts “speak” directly to your users.They produce instant feedback—assuming
users are not hearing impaired Fortunately, Apple built basic sound playback into the
Cocoa Touch SDK through System Audio services.This works very much like system
audio on a Macintosh
The alternatives include using Audio Queue calls or AVAudioPlayer Audio Queue
playback is expensive to program and involves much more complexity than simple alert
sounds need In contrast, you can load and play system audio with just a few lines of code
AVAudioPlayer also has its drawbacks It interferes with iPod audio In contrast, System
Audio can perform a sound without interrupting any music that’s currently playing,
although that may admittedly not be the result you’re looking for, as alerts can get lost in
the music
Alert sounds work best when kept short, preferably 30 seconds or shorter according to
Apple System Audio plays PCM and IMA audio only.That means limiting your sounds to
AIFF,WAV, and CAF formats
System Sounds
To build a system sound, call AudioServicesCreateSystemSoundIDwith a file URL
pointing to the sound file.This call returns an initialized system sound object, which you
can then play at will Just call AudioServicesPlaySystemSoundwith the sound object
That single call does all the work
Trang 8AudioServicesPlaySystemSound(mySound);
The default implementation of system sounds allows them to be controlled by the Sound
Effects preference in Settings.When effects are disabled, the sound will not play.To
over-ride this preference and always play the sound, you can set a property flag as such
// Identify it as a non UI Sound
When iPod audio is playing, the system sound generally plays back at the same volume, so
users may miss your alert Consider using vibration in addition to or in place of music.You
can check the current playback state by testing as follows Make sure you include
<MediaPlayer/MediaPlayer.h>and link to the MediaPlayer framework
if ([MPMusicPlayerController iPodMusicPlayer].playbackState ==
MPMusicPlaybackStatePlaying)
Add an optional system sound completion callback to notify your program when a sound
finishes playing by callingAudioServicesAddSystemSoundCompletion.Unless you use
short sounds that are chained one after another, this is a step you can generally skip
Clean up your sounds by calling AudioServicesDisposeSystemSoundIDwith the
sound in question.This frees the sound object and all its associated resources
Note
To use these system sound services, make sure to include
AudioToolbox/AudioServices.h in your code and link to the Audio Toolbox framework.
Vibration
As with audio sounds, vibration immediately grabs a user’s attention.What’s more,
vibra-tion works for nearly all users, including those who are hearing or visually impaired
Using the same System Audio services, you can vibrate as well as play a sound All you
need is the following one-line call to accomplish it, as used in Recipe 10-13:
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
You cannot vary the vibration parameters Each call produces a short one- to two-second
buzz On platforms without vibration support (like the iPod touch), this call does
nothing—but will not produce an error
Alerts
Audio Services provides a vibration/sound mashup called an alert sound, which is invoked
as follows
Trang 9419 Recipe: Simple Audio Alerts
This call, which is also demonstrated in Recipe 10-13, plays the requested sound and,
pos-sibly, vibrates or plays a second alert On iPhones, when the user has set Settings > Sound >
Ring >Vibrate to ON, it vibrates the phone Second generation and later iPod touch units
play the sound sans vibration (which is unavailable on those units) through the onboard
speaker First generation iPod touches play a short alert melody in place of the sound on
the device speaker while playing the requested audio through to the headphones
Delays
The first time you play back a system sound on the iPhone, you may encounter delays
You may want to play a silent sound on application initialization to avoid a delay on
sub-sequent playback
Note
When testing on iPhones, make sure you have not enabled the silent ringer switch on the
left side of the unit This oversight has tripped up many iPhone developers If your alert
sounds must always play, consider using the AVAudioPlayer class, which is discussed in
Chapter 15, “Audio, Video, and MediaKit.”
Recipe 10-13 Playing Sounds, Alerts, and Vibrations Using Audio Services
// create the sound
NSString *sndpath = [[NSBundle mainBundle]
pathForResource:@"basicsound" ofType:@"wav"];
CFURLRef baseURL = (CFURLRef)[NSURL fileURLWithPath:sndpath];
// Identify it as not a UI Sound
AudioServicesCreateSystemSoundID(baseURL, &mysound);
AudioServicesPropertyID flag = 0; // 0 means always play
Trang 10sizeof(SystemSoundID), &mysound, sizeof(AudioServicesPropertyID), &flag);
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 10 and open the project for this recipe.
One More Thing: Showing the Volume Alert
The iPhone offers a built-in alert that you can display to allow users to adjust the system
volume Figure 10-12 shows this alert, which consists of a slider and a Done button
Invoke this alert by issuing the following Media Player function
Test whether this alert is visible by issuing MPVolumeSettingsAlertIsVisible().This
returns a Boolean value reflecting whether the alert is already onscreen Hide the alert
withMPVolumeSettingsAlertHide(), which dismisses the alert regardless of whether the
user taps Done For these functions to work, you must link to the MediaPlayer framework
and import the media player headers
Trang 11421 Summary
Figure 10-12 The Media Player class’s utility
vol-ume alert panel.
Summary
This chapter introduced ways to interact directly with your user.You learned how to
build alerts—visual, auditory, and tactile—that grab your user’s attention and can request
immediate feedback Use these examples to enhance the interactive appeal of your
pro-grams and leverage some unique iPhone-only features Here are a few thoughts to carry
away from this chapter:
n Whenever any task will take a noticeable amount of time, be courteous to your
user and display some kind of progress feedback.The iPhone offers many ways to
do this, from heads-up displays to status bar indicators and beyond.You may need to
divert the non-GUI elements of your task to new thread to avoid blocking
n Alerts take users into the moment.They’re designed to elicit responses while
com-municating information And, as you saw in this chapter, they’re almost insanely
customizable It’s possible to build entire applications around the simple
UIAlertView
n Don’t be afraid of the run loop A modal response from an alert or action sheet lets
you poll users for immediate choices without being dependent on asynchronous
callbacks
Trang 12n If blue colored system-supplied features do not match your application design
needs, skip them.You can easily build your own alerts and menus using UIView
instances and animation
n Audio feedback including beeps and vibration can enhance your programs and
make your interaction richer Using system sound calls means that your sounds play
nicely with iPod functionality and won’t ruin the ongoing listening experience At
the same time, don’t be obnoxious Use alert sounds sparingly and meaningfully to
avoid annoying your users
Trang 1311
Creating and Managing
Table Views
Tables provide a scrolling list-based interaction class that works particularly well on a
small, cramped device Many if not most apps that ship natively with the iPhone and
iPod touch center on tables, including Contacts, Settings, iPod,YouTube, Stocks, and
Weather.The iPhone’s limited screen size makes tables, with their scrolling and individual
item selection, an ideal way to deliver information and content in simple,
easy-to-manipulate form In this chapter, you discover how iPhone tables work, what kinds of
tables are available to you as a developer, and how you can use table features in your own
programs
Introducing UITableView and
UITableViewController
The standard iPhone table consists of a simple scrolling list of individual cells, providing a
manipulatable data index Users may scroll or flick their way up and down until they find
an item they want to interact with.Then, they can work with that item independently of
other rows On the iPhone, tables are ubiquitous Nearly every standard software package
uses them, and they form the core of many third-party applications, too In this section,
you discover how tables function and what elements you need to bring together to create
your own
The iPhone SDK supports several kinds of tables, many of which are implemented as
flavors of the UITableViewclass In addition to the standard scrolling list of cells, which
provides the most generic table implementation, you can create several specialized tables
These include the kind of tables you see in the Preferences application, with their
blue-gray background and rounded cell edges; tables with sections and an index like the ones
used in the Contacts application; and related classes of wheeled tables, like those used to
set appointment dates and alarms No matter what type of table you use, they all work in
the same general way.They contain cells provided from a data source and respond to user
interactions by calling well-defined delegate methods
Trang 14TheUITableViewControllerclass derives from the UIViewControllerclass Like its
parent class, it helps you build onscreen presentations with minimal programming and
maximum convenience.The UITableViewControllerclass greatly simplifies the process
of creating a UITableView, reducing or eliminating the repetitive steps required for
work-ing directly with table instances.UITableViewControllerhandles the fussy details for the
table view layout and provides table-specific convenience by adding a local tableView
instance variable and automatic table protocol support for delegates and data sources
Creating the Table
To implement tables, you must define three key elements: how the table is laid out, the
kinds of things that are used to fill the table, and how the table reacts to user interaction
Specify these elements by adding descriptions and methods to your application.You
cre-ate the visual layout when building your views, you define a data source that feeds table
cells on demand, and you implement delegate methods that respond to user interactions
such as row-selection changes
Laying Out the View
UITableViewsinstances are, as the name suggests, views.They present interactive tables
on the iPhone screen.The UITableViewclass inherits from the UIScrollViewclass.This
inheritance provides the up and down scrolling capabilities used by the table Like other
views,UITableViewinstances define their boundaries through frames, and they can be
children or parents of other views.To create a table view, you allocate it, initialize it with a
frame just like any other view, and then add all the bookkeeping details by assigning data
source and delegate objects
UITableViewControllerstake care of the layout work for you.The
UITableViewControllerclass creates a standard UIViewControllerand populates it
with a single UITableView, setting its frame to allow for any navigation bars or toolbars
You may access that table view via the tableViewinstance variable
One important note:When subclassing UITableViewController, if you define a
loadViewmethod, be sure to call its superclass’s implementation—that is:
Doing this ensures that the table view is properly set up, while letting you add
custom features in the subclass such as navigation item buttons If you create your
UITableViewControllerusing Interface Builder, you do not have to add
any special calls to loadView
Trang 15425 Introducing UITableView and UITableViewController
Assigning a Data Source
UITableViewinstances rely on an external source to feed either new or existing table
cells on demand.This external source is called a data source and refers to the object whose
responsibility it is to return a cell to a table’s query
Data sources provide table cells based on an index path Index paths, objects of the
NSIndexPathclass, describe the path through a data tree to a particular node, namely
their section and their row Although many simple tables only use one section, tables can
use sections to split data into logical groups A UITableViewinstance uses index paths to
specify a section and the row within that section
It’s the data source’s job to connect that path to a concrete UITableViewCellinstance
and return that cell on demand.You can create an index path by supplying the section
and row:
myIndexPath = [NSIndexPath indexPathForRow:5 inSection:0];
Recover those values by using therowandsectionproperties of the index path object
The iPhone SDK provides a built-in mechanism for reusing table cells.When cells
scroll off the table and out of view, the table can cache them into a reuse queue.You can
tag cells for reuse and then pop them off that queue as needed.This saves memory and
provides a fast, efficient way to feed cells when users scroll quickly through long lists
onscreen Recipe 11-8 looks at cell reuse in more detail
You’re not limited to single cell types either.The following snippet chooses which of
two kinds of cells to request from the reusable cell queue Default cells provide a single
label; subtitle cells add a second.The identifier is arbitrary, as defined by the developer
Trang 16Use the table’s dataSourceproperty to assign an object to a table as its data source.That
object must implement the UITableViewDataSourceprotocol Most typically, the
UITableViewControllerthat owns the table view acts as the data source for that view
When working with UITableViewControllersubclasses, you need not declare the
pro-tocol as the parent class implicitly supports that propro-tocol and automatically assigns the
controller as the data source
After assigning a data source, load your table up with its cells by implementing the
tableView:cellForRowAtIndexPath:method On calling the table’s reloadData
method, the table starts querying its data source to load the actual onscreen cells into your
table.You can also call reloadDataat any time to force the table to reload its contents
Assigning a Delegate
Like many other Cocoa Touch interaction objects,UITableViewinstances use delegates to
respond to user interactions and implement a meaningful response.Your table’s delegate
can respond to events like the table scrolling or row selection changes Delegation tells the
table to hand off responsibility for reacting to these interactions to the object you specify,
typically the UITableViewControllerobject that owns the table view
If you’re working directly with a UITableView, use the standard setDelegate:
method to set your table’s delegate.The delegate must implement the UITableViewDelegate
protocol.When classes implement a delegate protocol, you add a declaration within the
class header file See Chapter 3,“Objective-C Boot Camp,” for an explanation of
declar-ing protocols
When working with UITableViewController, omit the setDelegate:method and
protocol assignment.That class automatically handles this A full set of delegate methods is
listed in the Apple SDK documentation, and the most basic ones are discussed in this
chapter
Note
UITableView instances provide notifications in addition to delegate method calls
Notifica-tions enable different threads of your application to communicate with each other by
broad-casting updates via the default NSNotificationCenter You can subscribe your
application to these notifications using standard NSNotificationCenter observers to find
out when the table states change With the 3.0 SDK, the only official table notification is
UITableViewSelectionDidChangeNotification.
Recipe: Implementing a Very Basic Table
TheUITableViewControllerclass embeds a UITableViewinto a UIViewController
object that manages its table view.This view is accessed via the tableViewproperty.These
controllers automatically set the data source and delegate methods for the table view to
itself So it’s really a plug-and-play situation For a really basic table, all you need to bring
to the table are some data and a few data source functions that feed cells and report the
number of rows and sections
Trang 17427 Recipe: Implementing a Very Basic Table
Figure 11-1 It’s easy to fill a UITableView with cells based on any array of strings This table presents the font family list from the UIFont class When tapped, the chosen item updates the font on the navigation bar at the top.
Populating a Table
Pretty much any array of strings can be used to set up and populate a table Recipe 11-1
leverages the UIFontclass’s capability to list available system fonts, that is, a handy list of
strings A call to [UIFont familyNames]returns an array populated with those font
names.This recipe creates a basic table based on those font names
Figure 11-1 shows the interface produced by this code, as run on the iPhone simulator
Be aware that running this application on the simulator produces an artificially long set of
fonts.That’s because the list is based on the available fonts from the Macintosh running
the SDK rather than the fonts on the iPhone itself
Data Source Methods
To display a table, every table data source must implement three core methods.These
methods define how the table is structured and provide contents for the table:
n numberOfSectionsInTableView—Tables can display their data in sections
or as a single list For simple tables, return 1.This indicates that the entire table should
be presented as one single list For sectioned lists, return a value of 2 or higher
Trang 18n tableView:numberOfRowsInSection—This method returns the number
of rows for each section.When working with simple lists, return the number of
rows for the entire table here For more complex lists, you’ll want to provide a way
to report back per section Section ordering starts with 0
n tableView: cellForRowAtIndexPath:—This method returns a cell to
the calling table Use the index path’s rowandsectionproperties to determine
which cell to provide and make sure to take advantage of reusable cells where
possi-ble to minimize memory overhead
Reusing Cells
One of the ways the iPhone conserves memory is by reusing cells.You can assign an
iden-tifier string to each cell.This specifies what kind of cell it is, and when that cell scrolls
off-screen allows that cell to be recovered for reuse Use different IDs for different kinds of
cells For simple tables, a single identifier does the job In the case of Recipe 11-1, it is
@"BaseCell".The strings are arbitrary Define them the way you want, but when using
multiple cell types keep the names meaningful.The discussion for Recipe 11-8, which
fol-lows later in this chapter, explores cell reuse
Before allocating a new cell, always check whether a reusable cell is available If your
table returns nilfrom a request to dequeueReusableCellWithIdentifier:, you need to
allocate a new cell
If the method returns a cell, update that cell with the information that’s meaningful for
the current row and section indices.You do not need to add cells to the reuse queue
Cocoa Touch handles all those details for you
Font Table Sample
Recipe 11-1 demonstrates how to build a simple list-based table It creates a table and fills
that table with all available font families.When tapped, the view controller assigns that
font to the label in the navigation bar at the top of the screen and prints a list of available
fonts for that family out to the debugger console.This behavior is defined in the
tableView:didSelectRowAtIndexPath:delegate method, which is called when a user
taps a row
Using the UITableViewControlleras a delegate is a good choice because the table’s
user interactions affect its views If you’d rather use another delegate, call setDelegate:
with that object to override the standard UITableViewControllersettings
Apple made several big changes in table view cells between the 2.x and 3.x SDKs
Prior to 3.0, you could set a cell’s textandimageproperties directly Starting with the 3.0
SDK, Apple introduced the textLabel,detailLabel, and imageViewproperties Each
property now points to an actual UI object (two UILabels and a UIImageView), offering
direct access to each object
Trang 19429 Recipe: Implementing a Very Basic Table
Note
Tables enable you to set the color for the selected cell by choosing between a blue or gray
overlay Set the selectionStyle property to either UITableViewCellSelection
➥ StyleBlue or UITableViewCellSelectionStyleGray If you’d rather not show a
selec-tion, use UITableViewCellSelectionStyleNone The cell can still be selected, but the
overlay color will not display.
Recipe 11-1 Building a Basic Table
#define MAINLABEL ((UILabel *)self.navigationItem.titleView)
@interface TableListViewController : UITableViewController
// Number of rows in use
return [UIFont familyNames].count;
}
- (UITableViewCell *)tableView:(UITableView *)tView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Attempt to dequeue a cell If this is not possible, create one
UITableViewCellStyle style = UITableViewCellStyleDefault;
UITableViewCell *cell = [tView
dequeueReusableCellWithIdentifier:@"BaseCell"];
if (!cell)
cell = [[[UITableViewCell alloc] initWithStyle:style
reuseIdentifier:@"BaseCell"] autorelease];
// Set the cell text
cell.textLabel.text = [[UIFont familyNames]
objectAtIndex:indexPath.row];
return cell;
}
Trang 20didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// React to cell selection by updating the title view text
NSString *font = [[UIFont familyNames]
[MAINLABEL setBackgroundColor:[UIColor clearColor]];
[MAINLABEL setTextColor:[UIColor whiteColor]];
[MAINLABEL setTextAlignment:UITextAlignmentCenter];
}
@end
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 11 and open the project for this recipe.
Recipe: Changing a Table’s Background Color
To use a color for your table’s background other than white, use the table view’s
backgroundColorproperty, as demonstrated in Recipe 11-2 Individual cells inherit this
color, producing a table whose components all show that color Make sure that you
choose a cell text color that compliments any table background color For a dark purple
background, as defined and used in this recipe, a strong white contrasts nicely
Unfortunately, you cannot change individual cell backgrounds directly.That is to say,
you can, by setting the cell’s backgroundColorproperty, but nearly all the color change
will happen behind label views.The labels block the cell’s background, obscuring it from
view.You will see few, if any, changes to the cell Set the table style to
UITableViewStyleGroupedfor the most (i.e.,“not much”) background visibility
Recipe 11-2 Changing the Background Color for a Table
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
Trang 21431 Recipe: Changing a Table’s Background Color
TableListViewController *tlvc = [[TableListViewController alloc]
init];
tlvc.tableView.backgroundColor = COOKBOOK_PURPLE_COLOR;
// Initialize Navigation Controller
UINavigationController *nav = [[UINavigationController alloc]
initWithRootViewController:tlvc];
nav.navigationBar.tintColor = COOKBOOK_PURPLE_COLOR;
// Create main window
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen
mainScreen] bounds]];
[window addSubview:nav.view];
[window makeKeyAndVisible];
}
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 11 and open the project for this recipe.
Updating the Background Color to Reflect the Degree of Scrolling
BecauseUITableViews are a subclass of the UIScrollViewclass, you can adapt your table
background color to the degree that a user has scrolled down the table For example, you
might lighten or darken the background color Use the percentage of distance as a
multi-plication factor for the color components used to tint the background
In their default state, all UITableViewControllerinstances are automatically set as
UIScrollViewdelegates No further work is needed before adding the following
UIScrollViewDelegatemethod to your UITableViewControllerimplementation.The
following code calculates background color saturation from the current table offset
- (void) scrollViewDidScroll: (UIScrollView *) sv
{
float percent = sv.contentOffset.y / sv.contentSize.height;
percent = 0.5 + (MAX(MIN(1.0f, percent), 0.0f) / 2.0f);
self.tableView.backgroundColor = [UIColor
colorWithRed:percent * 0.20392 green:percent * 0.19607
blue:percent * 0.61176 alpha: 1.0f];
}
Here are a few things to note about background color updates First, if you don’t enable
bouncing (i.e., allowing the table to bounce past the content edges and then move back),
decrease the divisor by the height of the table Second, make sure you set your initial
colors when setting up your table Otherwise, the color will “jump” the first time the user
Trang 22Figure 11-2 Combine a clear table background color with a backsplash to create a table that
scrolls over an image.
touches the table Finally, although this approach is not computationally overwhelming,
it does require constant screen updates and should be avoided for processor-heavy
applications
Recipe: Creating a Table Image Backsplash
Recipe 11-3 expands the background color idea presented in Recipe 11-2 to create a
table view with an image backdrop Instead of coloring the background to a solid hue, this
recipe uses a clear color with an alpha level of 0 By adding the backdrop to the
applica-tion window before adding the table view, the image bleeds through the table, as shown in
Figure 11-2
The table scrolls over the image, which remains static behind it Keep the imagery relevant
(for example, a corporate logo) and desaturated or otherwise lightened enough that it will
not interfere with the table’s text presentation Use a text color that contrasts well with the
background image
Recipe 11-3 Scrolling a Table over a Static Image
- (void)applicationDidFinishLaunching:(UIApplication *)application
Trang 23433 Recipe: Exploring Cell Types
// Create Table View Controller with a clear background
TableListViewController *tlvc = [[TableListViewController alloc]
init];
tlvc.tableView.backgroundColor = [UIColor clearColor];
// Initialize Navigation Controller
UINavigationController *nav = [[UINavigationController alloc]
initWithRootViewController:tlvc];
nav.navigationBar.tintColor = COOKBOOK_PURPLE_COLOR;
// Load in the backsplash image into a view
UIImageView *iv = [[[UIImageView alloc] initWithImage:[UIImage
imageNamed:@"Backsplash.png"]] autorelease];
// Create main window
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 11 and open the project for this recipe.
Recipe: Exploring Cell Types
The iPhone offers four kinds of base table view cells.These types, which are shown in
Figure 11-3, provide basic utilitarian cell implementations Each of these cell styles is new
to the 3.0 SDK (although the default style was used in 2.x, it has a new style name
con-stant) and represents a new way of creating and interacting with table cells
Before 3.0, you assigned a cell’s text directly Now cells provide both atextLabeland
adetailTextLabelproperty, which offer access to the labels themselves.With direct
label access, you can set each label’s text traits as desired Here is a round-up of the four
new styles:
n UITableViewCellStyleDefault—This cell offers a single left-aligned text
label and an optional image.When images are used, the label is pushed to the right,
decreasing the amount of space available for text.You can access and modify the
detailTextLabel, but it is not shown onscreen
n UITableViewCellStyleSubtitle—This cell, which is used in the iPod
application, pushes the standard text label up a bit to make way for the smaller detail
label beneath it.The detail label displays in gray Like the default cell, the subtitle cell
offers an optional image
Trang 24Figure 11-3 Cocoa Touch provides four standard cell types, some of which support optional images.
n UITableViewCellStyleValue1—This cell style, seen in the Settings
appli-cation, offers a large black primary label on the left side of the cell and a slightly
smaller, blue subtitle detail label to its right.This cell does not support images
n UITableViewCellStyleValue2—The Phone/Contacts application uses this
kind of cell, which consists of a small blue primary label on the left and a small
black subtitle detail label to its right.The small width of the primary label means
that most text will be cut off by an ellipsis.This cell does not support images
Recipe 11-4 shows the code that created the cells of Figure 11-3 It labels each cell with
the type in use and uses that same text as the reuse identifier Images are added to all cells
past the first four, demonstrating that only the default and subtitle presentations support
image display
Recipe 11-4 Creating Various Table Cell Styles
- (UITableViewCell *)tableView:(UITableView *)tView
Trang 25435 Recipe: Building Custom Cells in Interface Builder
// Dequeue a cell if possible, if not, create one.
UITableViewCell *cell = [tView
cell.imageView.image = [UIImage imageNamed:@"icon.png"];
// Set the cell text.
cell.textLabel.text = cellType;
cell.detailTextLabel.text = @"Subtitle text";
return cell;
}
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 11 and open the project for this recipe.
Recipe: Building Custom Cells in Interface Builder
Interface Builder makes it easy to create custom UITableViewCellinstances without
subclassing.You can build your cells directly in IB and load them in your code, which is
exactly what Recipe 11-5 does.The big problem about using IB is that your custom
Trang 26Figure 11-4 When working with cells created in Interface Builder, custom art, like that shown on the left, gets covered over by built-in cell content as
shown on the right.
elements are going to get covered by any cell content, as demonstrated by Figure 11-4
You may be aiming for the layout in the left image, but you usually end up with the
lay-out in the right
That’s because assigning a cell’s label’s properties cause the cell to create that label view
(plus any other necessary supporting views for that label) after the Interface Builder cell
has been loaded.Those extra views are placed on top of the cell, hiding your custom art
or any other IB elements you’ve placed into the cell
You might consider iterating through a cell’s subviews, setting their background color
to clear, but Apple frowns on view spelunking.There’s a simple, SDK-friendly way to
work around this Figure 11-5 (top) shows a basic UITableViewCellin Interface Builder,
and Figure 11-5 (middle) shows that same cell overlaid with the custom art from this
recipe.This is the content that the cell needs to present without being covered over like
Figure 11-4
The trick to preserving the cell art is to avoid using the cell’s built-in labeland
detailLabelproperties Instead, add a custom label (as shown in Figure 11-5, bottom)
and use that label instead of the built-in ones.The label view is tagged (in this case with
101) and recovered from the cell by using that tagging.You can set the tag in Interface
Builder’s attributes inspector.The following macro uses that tag to access the custom label
Trang 27437 Recipe: Building Custom Cells in Interface Builder
Figure 11-5 The top image shows a default cell created in Interface
Builder without any content The middle image shows that same cell after
adding custom art to the cell Adding a custom text label (bottom image)
helps create a properly labeled cell like the one shown in Figure 11-4 (left).
Figure 11-6 Cells built with custom labels in Interface Builder remain able to work with all stan- dard editing tasks including shifting to accommo- date the display of delete and delete confirmation
buttons.
When you need to use more than one label, for example for a subtitle, add another in
Interface Builder and tag it with a different number
Tables built with this approach are fully compliant with all table features.As Figure 11-6
shows, you can use standard editing with custom cells, and they will update, indent, and
otherwise behave like any other table cells If the label and image provided don’t fit your
purpose, build your own views and add them as cell subviews
Trang 28Tips for Creating Custom Cells
When building custom table view cells in Interface Builder, keep the following tips in mind:
n Create the new xib by choosing File > New File > User Interface > Empty XIB in
Xcode Name the file meaningfully, for example, BaseCell.xib, and save it
n Open the empty xib file in Interface Builder and drag a UITableViewCellinto
your project window
n Customize the cell contents by adding art and other interface items Be aware that
text-editing based classes such as UITextFieldandUITextViewdo not work well in
table view cells unless you take special care
n When adding custom items, try to clear enough space (about 40 pixels) on the right
side of the cell to allow the cell to shift right when entering edit mode Otherwise,
those items will be cut off
n Set the reuse identifier (e.g.,“BaseCell”), in the cell’s attributes inspector
(Com-mand-1).The identifier field lies near the top of the inspector
n You can set the cell’s image and selected image using the inspector, but in real life,
these are usually generated based on live data.You’ll probably want to handle any
image setting (via the imageandselectedImageproperties) in code Make sure
that the images you send are properly sized See the recipes about creating
thumb-nail versions of images in Chapter 7,“Working with Images.”
n You cannot pick a cell style in Interface Builder, and you cannot change a cell style
once you’ve loaded the nib If you need to use a cell style other than the default,
build your cell in code
n Use any cell height you need and then set the table’s rowHeightproperty to match
n Although Interface Builder offers a separator option in the cell’s attributes inspector,
you’ll want to use the table view’s separatorStyleandseparatorColorproperties
instead
Recipe 11-5 Using Custom Cells Built in Interface Builder
- (UITableViewCell *)tableView:(UITableView *)tView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Attempt to dequeue a cell If that’s not possible, load it.
UITableViewCell *cell = [tView
dequeueReusableCellWithIdentifier:@"BaseCell"];
if (!cell)
cell = [[[NSBundle mainBundle] loadNibNamed:@"BaseCell"
owner:self options:nil] lastObject];
// Set the cell text
[TEXTLABEL setText:
Trang 29439 Recipe: Alternating Cell Colors
return cell;
}
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 11 and open the project for this recipe.
Adding in Custom Selection Traits
When users select cells, Cocoa Touch provides you several ways to emphasize the cell’s
selection Customize a cell’s selection behavior by updating any of three traits.You can
change the image it shows, the color of its font, and the cell’s background.These are set
via the selectedImage,selectedTextColor, and selectedBackgroundViewproperties
The selected image replaces any image you have added to a cell (via the image
prop-erty, as shown in Recipe 11-4) when the user selects the cell.The selected version should
use the same size as the original so the cell layout remains stable For example, you might
want to replace an “empty” image, that is, a spaceholder, with an arrow, chevron, or finger
pointing into the cell that has been selected
The selected text color property is officially deprecated despite the fact that it is still
used in Interface Builder.The Apple documents suggest using the new textLabel
prop-erty but do not provide an easy way to hook into that object for selection/deselection
updates Until Apple addresses the issue, you can use the workaround shown in the
follow-ing snippet, which avoids compile-time deprecation warnfollow-ings:
cell.selectedBackgroundView = [[[UIImageView alloc]
initWithImage:[UIImage imageNamed:@"cellart.png"]] autorelease];
// This is deprecated but it still works and is used in IB
[cell performSelector:@selector(setSelectedTextColor)
withObject:COOKBOOK_PURPLE_COLOR];
TheselectedBackgroundViewproperty works exactly as you’d want the regular
backgroundViewproperty to work but does not (refer to Figure 11-4).When a cell is
selected, the selected background appears behind the text, providing a perfect blend
between art and text
Recipe: Alternating Cell Colors
Although blue and white cell alternation is a common and highly requested table feature,
Apple did not include that option in its iPhone SDK.The custom cell techniques shown
previously in Recipe 5 let you import a cell designed in Interface Builder Recipe
11-6 builds the alternating white/blue cell structure shown in Figure 11-7 by working with
not one but two custom cell xibs
Trang 30Figure 11-7 Use custom cells to create
alternat-ing blue and white cells.
A simple even/odd check (row % 2) specifies whether to load a blue or white cell
Because this table uses just one section, it simplifies the math considerably Blue/white
alternating cells work best for nongrouped, nonsectioned tables both visually and
pro-grammatically
Notice how this recipe uses cell identifiers to reuse already loaded cells as needed.The
xibs use the same identifiers as their filenames, considerably simplifying this code New
blue or white cells are not created if existing ones can be consumed from the reuse queue
Be aware that although this cell style works with edits, both deletion and reordering,
you’ll want to reload the table after each user change to keep the blue/white/blue/white
ordering As the user drags an item into place, it will retain its original coloring, possibly
causing a visual discontinuity until the edit finishes For reordering, issue that reload
com-mand using a delayed selector of at least a quarter to half a second
Recipe 11-6 Building a Table with Alternately Colored Cells
- (UITableViewCell *)tableView:(UITableView *)tView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Choose the cell kind
NSString *identifier = (indexPath.row % 2) ?
@"WhiteCell" : @"BlueCell";
Trang 31441 Recipe: Building a Custom Cell with Built-In Controls
// Attempt to dequeue Load if that’s not possible.
UITableViewCell *cell = [tView dequeueReusableCellWithIdentifier:
identifier];
if (!cell)
cell = [[[NSBundle mainBundle] loadNibNamed:identifier
owner:self options:nil] lastObject];
// Set the cell text
[(UILabel *)[cell viewWithTag:101] setText:
[[UIFont familyNames] objectAtIndex:indexPath.row]];
return cell;
}
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 11 and open the project for this recipe.
Recipe: Building a Custom Cell with Built-In
Controls
When using Interface Builder to design a custom cell, you’re not limited to background
art and labels It’s easy enough to add buttons or other controls that act in cell-native ways
Recipe 11-7 manages the cells shown in Figure 11-8.These cells include a main text
label, which is used to display a font name; a subtitle label, which presents a standard
phrase using that font; and a family button that displays a list of all members of a given
font family via an alert
Rather than use a custom UITableViewCellas Recipe 11-6 did, Recipe 11-7 creates a
subclass.CustomCellintroduces three outlets.These include the button and the two
labels And it adds an action,buttonPress:, which is called for touch-up-inside events
The connections between the IBOutlets,IBAction, and their targets are all made directly
in Interface Builder
To make this recipe work, you must create a UITableViewCellinstance Import the
class header for CustomCell(select File > Read Class Files) and then use the Identity
Inspector (Tools > Identity Inspector, Command-4) to change that instance’s class from
UITableViewCelltoCustomCell Once that’s done, you can wire up the outlets and
button callback connections using Interface Builder’s drag-to-connect features
Trang 32Figure 11-8 The button added in Interface Builder for this custom cell (top) launches an alert with a list of font families (bottom) Each button is tied to its own cell and works whether or not the cell is selected.
Recipe 11-7 Creating an Embedded Cell Control Callback
@interface CustomCell : UITableViewCell {
IBOutlet UIButton *button;
IBOutlet UILabel *primaryLabel;
IBOutlet UILabel *secondaryLabel;
}
@property (assign) UIButton *button;
@property (assign) UILabel *primaryLabel;
@property (assign) UILabel *secondaryLabel;
- (IBAction) buttonPress: (UIButton *) aButton;
Trang 33443 Recipe: Remembering Control State for Custom Cells
{
NSString *fontName = self.primaryLabel.text;
NSArray *fonts = [UIFont fontNamesForFamilyName:fontName];
UIAlertView *av = [[[UIAlertView alloc] initWithTitle:fontName
message:[fonts componentsJoinedByString:@", "] delegate:nil
cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
[av show];
}
@end
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 11 and open the project for this recipe.
Recipe: Remembering Control State for Custom
Cells
Cells have no “memory” to speak of.They do not know how an application last used
them.They are views and nothing more.That means if you reuse cells without tying those
cells to some sort of data model, you can end up with unexpected and unintentional
results.This is a natural consequence of the Model-View-Controller design paradigm
Consider the following scenario Say you created a series of cells each of which owned
a toggle switch Users can interact with that switch and change its value A cell that scrolls
offscreen, landing on the reuse queue, could therefore show an already-toggled state for a
table element that user hasn’t yet touched
Figure 11-9 demonstrates this problem.The cell used for Item A was reused for Item
L, presenting an OFF setting, even though the user has never interacted with Item L It’s
the cell that retains the setting, not the logical item Don’t depend on cells to retain state
that way
To fix this problem, check your cell state against a stored model.This keeps the view
consistent with your application semantics Recipe 11-8 uses a custom dictionary to
asso-ciate cell state with the cell item.There are other ways to approach this problem, but this
simple example provides a taste of the model/view balance needed by a data source
whose views present state information
Since the state is stored in the table view controller, each cell needs to be able to “call
home” so to speak when its switch updates its state.The custom tableViewController
property that is set here provides that back link, and the customSwitchproperty accesses
the current user-set state
Trang 34Figure 11-9 The cell used to present Item A (left) is reused to present Item L (right) while retaining its previous switch setting.
Recipe 11-8 Using Stored State to Refresh a Reused Table Cell
- (UITableViewCell *)tableView:(UITableView *)tView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Dequeue a cell if possible
CustomCell *cell = (CustomCell *)[tView
dequeueReusableCellWithIdentifier:@"BaseCell"];
if (!cell)
cell = [[[NSBundle mainBundle] loadNibNamed:@"BaseCell"
owner:self options:nil] lastObject];
// Determine the key and state based on the row
NSString *key = [ALPHA objectAtIndex:indexPath.row];
Trang 35445 Recipe: Remembering Control State for Custom Cells
[self.switchStates setObject:[NSNumber numberWithBool:YES]
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 11 and open the project for this recipe.
Visualizing Cell Reuse
Recipe 11-8 helps fix problems with cell/model discrepancies.The following code snippet
visualizes exactly how your cells are getting reused.This implementation tags each new
cell on creation, letting you track how each cell is used and reused in the lifetime of a very
large table In this case, the table is about a million items long I encourage you to test this
snippet out (a full version is included in the sample code for this book) and energetically
scroll through the list in both directions.You’ll see that with a jerky enough interaction
style you can really mix up your cell ordering.You’ll also discover that even for a million
item table, you’ll max out at about 11 table cells total
Trang 36{
UITableViewCellStyle style = UITableViewCellStyleDefault;
UITableViewCell *cell = [tView
dequeueReusableCellWithIdentifier:@"BaseCell"];
// Create a new cell with a unique number whenever
// a cell cannot be dequeued
Each cell implements the prepareForReusemethod, which is invoked before a cell can
be returned from the table view’s dequeue request.You can subclass UITableViewCelland
override this method to reset content before reusing a cell
Recipe: Creating Checked Table Cells
Accessory views expand normal UITableViewCellfunctionality.The most common
accessories are the Delete buttons and drag bars for reordering, but you can also add check
marks to create interactive one-of-n or n-of-n selections.With these kinds of selections,
you can ask your users to pick what they want to have for dinner or choose which items
they want to update.This kind of radio button/check box behavior provides a richness of
table interaction Recipe 11-9 demonstrates how to create this kind of table
Figure 11-10 shows checks in an interface, a standardUITableViewwith accessorized
cells Check marks appear next to selected items.When tapped, the checks toggle on or
off Like Recipe 11-8, this recipe uses a shared dictionary to track which logical items are
checked, avoiding inconsistency issues that arise from cell reuse
Checked items use the UITableViewCellAccessoryCheckmarkaccessory type
Unchecked items use the UITableViewCellAccessoryNonevariation.You set these by
assigning the cell’s accessoryTypeproperty
Note that it’s the cell that’s being checked here, not the logical item associated with the
cell (although that logical item’s value is updated in the shared stateDictionary)
Reused cells remain checked or unchecked at next use so you must always set the
acces-sory to match the state dictionary when dequeuing a cell Recipe 11-8 discussed
preserv-ing cell state
Trang 37447 Recipe: Creating Checked Table Cells
Figure 11-10 Check mark accessories offer a convenient way of making one-of-n or n-of-n selec-
tions from a list.
Recipe 11-9 Using Accessory Check Marks with Cells
- (UITableViewCell *)tableView:(UITableView *)tView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Retrieve or create a cell
UITableViewCellStyle style = UITableViewCellStyleDefault;
UITableViewCell *cell = [tView
dequeueReusableCellWithIdentifier:@"BaseCell"];
if (!cell) cell = [[[UITableViewCell alloc] initWithStyle:style
reuseIdentifier:@"BaseCell"] autorelease];
// Set cell label
NSString *key = [@"Row " stringByAppendingString:[ALPHA
objectAtIndex:indexPath.row]];
cell.textLabel.text = key;
// Set cell checkmark
NSNumber *checked = [self.stateDictionary objectForKey:key];
if (!checked) [self.stateDictionary setObject:(checked = [NSNumber
numberWithBool:NO]) forKey:key];
cell.accessoryType = checked.boolValue ?
Trang 38UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
// Recover the cell and key
UITableViewCell *cell = [self.tableView
cellForRowAtIndexPath:indexPath];
NSString *key = cell.textLabel.text;
// Created an inverted value and store it
BOOL isChecked = !([[self.stateDictionary objectForKey:key]
boolValue]);
NSNumber *checked = [NSNumber numberWithBool:isChecked];
[self.stateDictionary setObject:checked forKey:key];
// Update the cell accessory checkmark
cell.accessoryType = isChecked ? UITableViewCellAccessoryCheckmark
: UITableViewCellAccessoryNone;
}
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 11 and open the project for this recipe.
Recipe: Removing Selection Highlights from Cells
There are times when working with tables that you need to avoid retaining a cell state.This
happens when you want users to be able to interact with the table and touch cells, but you
don’t want to maintain that selected state after the user has finished the interaction Cocoa
Touch offers two approaches for tables that need to deny persistent cell selection
For the first approach you can set a cell’s selectionStyleproperty to
UITableViewCellSelectionStyleNone.This disables the blue or gray overlays that
dis-play on the selected cell, like the one shown in Figure 11-10 for Row F The cell is
still selected but will not highlight on selection in any way If selecting your cell produces
some kind of side effect other than presenting information, this is not the best way to
approach things Instead, consider the following
The second approach allows the cell to highlight but removes that highlight after the
interaction completes.You do that by telling the table to deselect the cell in question In
Recipe 11-10, each user selection triggers a delayed deselection (the custom deselect:
method defined in the recipe) after a half a second This method calls the table view’s
Trang 39449 Recipe: Working with Disclosure Accessories
deselectRowAtIndexPath:animated:method, which fades away the current selection
Using this approach offers both the highlight that confirms a user action and the state-free
display that hides any current selection from the user
Recipe 11-10 Deselecting a Table Row
// Perform the deselection
- (void) deselect: (id) sender
printf("User selected row %d\n", [newIndexPath row] + 1);
[self performSelector:@selector(deselect) withObject:nil
afterDelay:0.5f];
}
Get This Recipe’s Code
To get the code used for this recipe, go to http://github.com/erica/iphone-3.0-cookbook-, or
if you’ve downloaded the disk image containing all of the sample code from the book, go to
the folder for Chapter 11 and open the project for this recipe.
Recipe: Working with Disclosure Accessories
Disclosures refer to those small, blue or gray, right-facing chevrons found on the right of
table cells Disclosures help you to link from a cell to a view that supports that cell In the
Contacts list and Calendar applications, these chevrons connect to screens that help you to
customize contact information and set appointments Figure 11-11 shows a table view
example where each cell displays a disclosure control, showing the two available types
The blue and gray chevrons have two roles.The blue
UITableViewCellAccessoryDetailDisclosureButtonversions are actual buttons.They
respond to touches and are supposed to indicate that the button leads to a full interactive
detail view.The gray UITableViewCellAccessoryDisclosureIndicatordoes not track
touches and should lead your users to a further options view, specifically options about
that choice
You see these two accessories in play in the Settings application In the Wi-Fi
Net-works screen, the detail disclosures lead to specific details about each WiFi network: its IP
address, subnet mask, router, DNS and so forth.The disclosure indicator for “Other”
enables you to add a new network by scrolling up a screen for entering network
informa-tion A new network then appears with its own detail disclosure
Trang 40Figure 11-11 The right-pointing chevrons cate disclosure controls, allowing you to link individ-
indi-ual table items to another view.
You also find disclosure indicators whenever one screen leads to a related submenu
When working with submenus, stick to the simple gray chevron.The rule of thumb is
this: Submenus use gray chevrons, and object customization uses blue ones Respond to
cell selection for gray chevrons and to accessory button taps for blue chevrons
Recipe 11-11 demonstrates how to use disclosure buttons (the blue accessories)
in your applications.This code sets the accessoryTypefor each cell to
UITableViewCellAccessoryDetailDisclosureButton Importantly, it also sets
editingAccessoryTypetoUITableViewCellAccessoryNone.When your delete or
reorder controls appear, your disclosure chevron will hide, enabling your users full
control over their edits without accidentally popping over to a new view
To handle user taps on the disclosure, the tableView:accessoryButtonTappedForRow
➥ WithIndexPath:method enables you to determine the row that was tapped and
imple-ment some appropriate response.This sample merely pushes a new UIViewController
that displays a stock image In real life, you’d move to a view that explains more about the
selected item and enables you to choose from additional options
Gray disclosures use a different approach As these accessories are not buttons, they
respond to cell selection rather than the accessory button tap Add your logic to
tableView:didSelectRowAtIndexPath:to push the disclosure view onto your
naviga-tion stack or by presenting a modal view controller