An introduction to actions (iOS 4)

If you won’t usually be programming directly with events, how will you access user input? The answer is by using actions. You’ll typically depend on preexisting text views, buttons, and other widgets to run your programs. When using these objects, you don’t have to worry about raw events. Instead, you can build programs around control events and actions that are generated by UIControls. Let’s look at the UIControl object first; then, we’ll examine the relationship between control events and actions and how to hook them up.

The UIControl object

When you were working with events, you found that the UIResponder class held many of the methods critical for event control. Similarly, you can access a lot of the methods important to SDK controls through the UIControl class.

UIControl is a child of UIView (and thus UIResponder). It’s the parent of important user interface controls such as UIButton, UISwitch, UIPageControl, UISegmented-Control, UISlider, and UITextField. It’s not used for some other control-looking objects such as UISearchBar, so you should check the Apple class references before trying to use its functionality. Also note that the higher-level UIControl class can’t be used on its own; it defines the common methods used by its children.

The UIControl class contains several properties that control its basic setup, such as enabled (which determines whether it’s on), highlighted (which determines its visual state), and selected (which sets Boolean state for appropriate sorts of controls, such as switches). You can also directly access a control’s touch events with beginTracking-WithTouch:withEvent:, continueTrackingWithTouch:withEvent:, and endTrack-ingWi thTouch: wi thEvent:, methods that work in a similar way to the event response functions that you played with in UIResponder. But you won’t be using these methods, because they don’t represent the simple advantages that you’ll see when using control objects. For that, we turn to UIControl’s action-target mechanism.


Control events and actions

The UIControl object introduces a new event-handling infrastructure that takes touch events of the sort that you might have directly handled in the previous section and (eventually) converts them into simple actions, without your having to worry about the specifics of how a user accessed a control. The complete sequence of events is outlined in figure 6.6.

 UIControl objects take standard touch events and turn them into actions that are dispatched by UIApplication.

Figure 6.6 UIControl objects take standard touch events and turn them into actions that are dispatched by UIApplication.

When a touch event arrives at a UIControl object (via normal dispatching along the responder chain), the control does something unique. Inside the standard UIResponder methods that you used in the previous section (such as touches-Began:withEvent:), a UIControl object turns standard touch events into special control events.

These control events broadly describe how the user has interacted with the controls rather than recording gestures. For example, they may report that a button has been pushed or a slider moved. They’re divided into three categories: touch events, editing events, and a slider event. The touch events describe how a user’s finger interacted with the control, the editing events describe changes to a UITextField, and the UIControlEventValueChanged event describes changes to a UISlider.

These control events are all enumerated in a bitmask that’s defined in the UIControl object. An almost-complete listing of them—including some composite control events—can be found in table 6.5. We’ve left out only a few reserved values.

Table 6.5 UIControl objects recognize a number of special events.

Value

Summary

UIControlEventTouchDown

A finger touch.

UIControlEventTouchDownRepeat

A repeated finger touch (with tapCount > 1).

UIControlEventTouchDragInside

A finger movement ending inside the control.

UIControlEventTouchDragOutside

A finger movement ending just outside the control.

UIControlEventTouchDragEnter

A finger movement that enters the control.

UIControlEventTouchDragExit

A finger movement that exits the control.

UIControlEventTouchUpInside

A finger removed from the screen inside the control.

UIControlEventTouchUpOutside

A finger removed from the screen outside the control.

UIControlEventTouchCancel

A system event canceled a touch.

UIControlEventValueChanged

A slider (or other similar) object changed its value.

Table 6.5 UIControl objects recognize a number of special events.

Value

Summary

UIControlEventEditingDidBegin

Editing began in a UITextField.

UIControlEventEditingChanged

Editing changed in a UITextField.

UIControlEventEditingDidEnd

Editing ended in a UITextField due to a touch outside the object.

UIControlEventEditingDidEndOnExit

Editing ended in a UITextField due to a touch.

UIControlEventAllTouchEvents

Composite for all the touch-related events.

UIControlEventAllEditingEvents

Composite for the editing-related events.

UIControlEventAllEvents

Composite for all events.

After a standard event has been turned into a control event, a sequence of additional methods is called, as shown in figure 6.6. First, the UIControl object calls send-ActionsForControlEvents:. That in turn breaks down the events it’s been sent and calls sendAction:to :forEvent: once per event. Here, the control event is turned into an action, which is a specific method that’s going to be run in a specific target object. Finally, the UIApplication method sendAction:to:fromSender:forEvent: is called by the control, again once per event.

This is another situation where the application object does big-picture controlling of messaging. The application sends the action to the target object. But there’s one catch: if the target that the action is being sent to has been listed as nil, the action is sent to the first responder instead and from there moves up the responder chain.

That process can be slightly exhausting, and fortunately you shouldn’t normally need to know its details. For your purposes, you should be aware that a UIControl object turns a touch event first into a control event and then into an action with a specific recipient. Even better, you need to code only the last part of that conversion, from control event into targeted action.

Using addTarget:action:forControlEvents:

A UIControl object maintains an internal dispatch table that correlates control events with target-action pairs. This table says which method should be run by which object when a specified event occurs. You can add entries to this table with the UIControl object’s addTarget:action:forControlEvents: method. The following example shows how it works:

tmp12150_thumb

The first argument, addTarget:, says where the message will be sent. It’s frequently set to self, which usually refers to a view controller that instantiated the control object.

The second argument, action:, is the trickiest. First, note that it uses the @ syntax that we mentioned in topic 2. The selector should identify the name of the method that’s going to be run in the target object. Second, be aware that you can send the action argument either without a colon (method) or with a colon (method:). In the latter case, the ID of the controlObject is sent as an argument. Be sure your receiving method is correctly defined to accept an argument if you include that colon in your selector.

The third argument, forControlEvents:, is a bitmasked list of possible control events, taken from table 6.5.

With all these puzzle pieces in place, you’re ready to write some code that uses actions (and this method). As a simple example, you’ll expand the functionality to your event reporter by adding a reset button.

Next post:

Previous post: