Tuesday, 6 May 2014

Learning by Example [Got Views?]

Software development is a lot like cooking. Its one thing to read recipes, talk about the process, and enjoy the results. Its another thing to actually do it. One of the best ways to learn how to cook is to watch someone whoknows what they’re doing, and emulate them.

Apple provides many example projects—fully written, ready to run apps—that demonstrate the use of various technologies in iOS. All you have to do is download one, build it, run it, and then mine it for all of its secrets. Theseexample projects are a great way to get started using, or at least understanding how to use, many of the frameworks and features in iOS.

Not only does Apple provide these example projects free of charge, they’ve made it ridiculously simple to download them. Xcode will search for, download, and open sample code projects with the click of a button. Start in Xcodes documentation organizer (Help  Documentation and API Reference) window, as shown in Figure 10-1.


Figure 10-1. Searching for sample code

Search for the UICatalog project, as shown in Figure 10-1. It will appear under the Sample  Code category. Click on it and the projects documentation page appears. At the top is an Open Project button. Click it. Xcode downloads the projects ZIP file, un-archives it, and opens the project in a new workspace window, as shown in
Figure 10-2. How easy was that?


Figure 10-2. UICatalog project

You’ll find that the documentation for many classes contains links to sample projects, making it easy to download code that shows you those classes in action.

The UICatalog project is extra special. Its an iPhone app that demonstrates every major view object supplied by iOS. So not only is it a handy visual reference to the kinds of view objects iOS supplies, but you can see exactlyhow these objects are created and used in an app.

Run the UICatalog app in an iPhone simulator (or on your own device, if you like). First in the list is buttons, as shown in Figure 10-3, and thats a great place to start.


Figure 10-3. UICatalog app

Buttons

A button is a very straightforward view object; it acts like a physical button. The UIButton class draws a button and observes touch events to determine how the user is interacting with it. It translates what the user is doinginto action events, such as “user touched inside the button,” “user moved their finger outside the button,” “user moved back inside the button,” and “user released their finger while still inside the button.” Thats pretty muchall it does.

I know what you’re thinking. Well, maybe I dont. But I hope you’re thinking, “but a button does more than that! It sends action messages to another object, it remembers its state, it can be disabled, and it can have gesturerecognizers attached to it. Thats a lot!”

It is a lot, but the UIButton class doesnt do any of those things. UIButton is at the end of a chain of classes, each of which is responsible for one set of closely related behaviors. Software engineers say that each class performs a role. The role of a UIButton object is to act like a button. Other classes do all of that other stuff. So that you can get a clearer picture of whats going on, I think its time for you to dissect a UIButton. This will notonly help you understand how UIButton was built, but how all control views are constructed.

The Responder and View Classes

A UIButton is a subclass of UIControl, which is a subclass of UIView, which is a subclass of
UIResponder. Each class adds one layer of functionality that, taken together, makes a button.

The UIResponder class defines all of the event-related functions of the objects, most notably the methods that handle touch events. You learned all about UIResponder in Chapter 4, and you created a custom UIView object thatoverrode the touch event handling methods with your own, so I wonrepeat any of that here.

The next layer that UIButton inherits is UIViewUIView is a big, complicated class. It has dozens of properties and over a hundred methods. Its huge because its responsible for every aspect of how every visible object in theiOS universe gets displayed on a screen. It handles the geometry of the view, its coordinate systems, transformations (like rotation, scaling, and skewing), animation, how the view gets repositioned when the screen sizechanges, and hit testing. Its also responsible for drawing itself, drawing its subviews, deciding when those views need to be redrawn, and more.
One, seemingly unrelated, property of UIView is its gestureRecognizers property. The UIView class doesnt do anything with gesture recognizers directly. But a UIView defines a visible region of the display, and any visible region can have a gesture recognizer attached to it, so that property exists in UIView.

HOW GESTURE RECOGNIZERS GET EVENTS

Gesture recognizers are fed events by the UIWindow  object during touch event delivery. In Chapter 4, I explained that hit testing is used to determine the view that will receive the touch events. That description oversimplifiedthe process somewhat.

Starting with iOS 3.2, the UIWindow first looks at the initial (hit test) view to see if it has any gesture recognizer objects attached to it. If it does, the touch events are first sent to those gesture recognizer objects, instead ofbeing delivered directly to the view object. 

If the gesture recognizers aren’t interested, then the event eventually makes its way to the view object.
If you need to, there are a variety of ways to alter this behavior, but its a tad complicated. For all of the details, read the “Gesture Recognizers”  chapter of the Event Handling Guide for iOS, that you’ll find in 
XcodesDocumentation  and API Reference.

So everything thats visual about the button is defined in the UIView class. Now move on to the next layer, the UIControl class.

The Control Class

UIControl is the abstract class that defines the properties common to all control objects. This includes buttons, sliders, switches, steppers, and so on. A control object:

n     Sends action messages to target objects

n     Can be enabled or disabled

n     Can be selected

n     Can be highlighted

n     Establishes how content is aligned
The first item in the above list is the most important. The UIControl class defines the mechanism for delivering action messages to recipients, typically controller objects. Every UIControl object maintains a table of events thattrigger actions, the object that will receive that action, and the action message it will send. When you’re editing an Interface Builder file and you connect an event to an action method in another object, you’re adding one entry tothat objects event dispatch table.

The other properties (enabled, selected, and highlighted) are general indicators of the controls appearance and behavior. Subclasses of UIControl determine exactly what those properties mean, if anything.

The enabled property is the most consistent. A control object interacts with the user when enabled, and ignores touch events when disabled (control.enabled=NO). Most control classes indicate that they are disabled bydimming, or graying, their image to show the user the control is inert.

The highlighted property is used to indicate that the user is currently touching the control. Many controls “light up” when touched, and this property reflects that.

The selected property is for controls that can be turned “on” or “off,” such as the UISwitch class.

Controls that dont, such as buttons, ignore this property.

The UIControl class also introduces the concept of an alignment (vertical and horizontal) through the contentVerticalAlignment and contentHorizontalAlignment properties. Most control objects have some sort of title or image anduse these properties to position that in the view.


Button Types

You’ve now worked your way back to the UIButton class. Its this class that implements the
button-specific behavior of a control+view+responder object. The UIButton class supplies a handful of pre-defined button looks, along with a plethora of customizations so you can make it look just about any way you want.

The most important property of a button is its type. A button can be one of these types:

n     Rounded Rectangle

n     Custom

n     A “disclose detail” arrow

n     An “info” button (light or dark)

n     An “add contact” plus symbol

All of these button types, except custom, are shown in the UICatalog app, as shown in Figure 10-4. The important thing to remember is that a buttons type is determined when it is created. Unlike all of its other properties, itcannot be changed afterwards. A rounded rectangle button is a rounded rectangle button for life.


Figure 10-4. Buttons

The rounded rectangle button is the workhorse of iOS. Its the standard, default, button style used throughout the iOS interface. You’ll also notice that theres nothing rounded” about a Rounded Button (middle-left of Figure 10-4).iOS 7 introduced a new, streamlined, UI design that echews the skeuomorphic button design of earlier versions. The class and constant names, however, have not changed. Choose the rounded” button when you want to presentthe standard button design for the version of iOS your users are running.

The custom button style is a blank canvas. iOS (all versions) adds nothing to the look of a custom button, allowing you complete control over its appearance. You used the custom button style for the Surrealists app in Chapter2.

You can dramatically alter a buttons basic look by adjusting its color, text, text style, or even supply your own images for the buttons title and background.

The premier properties that adjust your buttons look are:

n     Tint color

n     Title text (plain or attributed) and color

n     Foreground image

n     Background image or color

The tintColor property sets the highlight and accent color of rounded rectangle buttons. The standarcolor is blue. Other button types ignore this property.

The buttons title can be a simple string value (which you’ve used in your projects so far), or it can be attributed string. An attributed string is a string that includes text attributes: font, size, italics, bold, subscript offset, and soon. Creating attributed strings is a bit complicated, but allows you to create buttons with whatever font and style the system is capable of. I describe attributed strings in Chapter 20.

You can also use an image instead of text for your buttons label by setting the image property. Similarly, the background can be set to an image or a solid color. You can also mix these in any combination you want: text titleover an image background, image over a solid color background, image with no background (by setting the background color to UIColors clearColor object), and so on.

The buttons with the rounded rectangle look (in the upper-left of Figure 10-4) are supplying theiown background image, whiteButton.png in this case. Images used for buttons background can utilize the cap insets(capInsets) property to define a margin around the edge of the image that is not scaled when the image is stretched to fit the size of the button. This feature lets you
design a single graphic image that will fill any button size, without distorting its edges. Compare the
whiteButton.png resource image in Xcode with how it appears in the button when the app runs.

The remaining button types (detail disclosure, info, add contact, and so on) are predefined buttons with few options for customization. Use these types where your app provides those exact features, and your users willunderstand exactly what they mean.


Control States

When creating and configuring the buttons title, image, background image, and background color, you must consider the various states the button (control) can be in. The UIControls enabledhighlighted, and selected propertiescombine to form a single state value (UIControlState) for that control. The state will always be one of: normal, highlighted, disabled, or selected.

When the button is displaying normally, its state is UIControlStateNormal. When the user is touching it, its state changes to UIControlStateHighlighted. When its disabled, its state becomes UIControlStateDisabled.

When you set a buttons title, image, background, or color you do so for a particular state. This allows you to set one button image for when the button is enabled and alternate button image(s) for when its disabled,highlighted, or selected. You see this reflected in the methods that set these properties:

-  (void)setTitle:(NSString *)title  forState:(UIControlState)state
-  (void)setTitleColor:(UIColor *)color forState:(UIControlState)state
-  (void)setImage:(UIImage *)image  forState:(UIControlState)state
-  (void)setBackgroundImage:(UIImage *)image  forState:(UIControlState)state

You dont have to set values for every state. At a minimum, you should set the value for the normal (UIControlStateNormal) state. If thats all you set, that value will be used for all other states. If you then want it to have a differenttitle, image, background, or color for one of the other states, set that too.

There are lots of other, subtler, properties for fine-tuning your buttons look and feel. You can,
for example, control the shadow thrown by the title text or change the position (inset) of the title, image, and background image. Read through the documentation for UIButton for all of the available properties.

The last four button types—disclosure arrow, info (light), info (dark), and add contact—arconvenience types for well-defined user interface buttons. There is almost nothing about the look or behavior of these buttons that youcan customize.

Button Code

You now know enough about button properties to take a peek at the button construction code in UICatalog. Up to now, you’ve created button objects using Interface Builder—which is fine, theres nothing wrong with that. Butyou can also create any iOS object programmatically, as you’ve done with other objects like arrays and images.

The UICatalog app creates most of its objects programmatically, and it even provides hints as to where that happens so you can go find the code. In Figure 10-4, the text underneath the button says “ButtonsViewController.m:(UIButton*)roundedButtonType.” Switch back to Xcode and find the ButtonsViewController.m file. Click on it and locate the -roundedButtonType method. It should look something like this:

-  (UIButton  *)roundedButtonType
{
if (roundedButtonType == nil)
{
roundedButtonType = [[UIButton  buttonWithType:UIButtonTypeRoundedRect] retain]; roundedButtonType.frame = CGRectMake(182.0,  5.0,
kStdButtonWidth, kStdButtonHeight); [roundedButtonType setTitle:@"Rounded"  forState:UIControlStateNormal]; roundedButtonType.backgroundColor = [UIColor clearColor];[roundedButtonType addTarget:self action:@selector(action:)
forControlEvents:UIControlEventTouchUpInside]; roundedButtonType.tag = kViewTag;
}
return  roundedButtonType;
}

This method lazily creates the button that appears in the UICatalog app as “Rounded Button.” If you want to try out different rounded rectangle button properties to see what they look like, fiddle with this code and run the appagain.

No comments:

Post a Comment