For the More Curious: UIControl

The class UIControl is the superclass for several classes in Cocoa Touch, including UIButton and UISlider. You have seen how to set the targets and actions for these controls. Now we can take a closer look at how UIControl overrides the same UIResponder methods you implemented in this chapter.

In UIControl, each possible control event is associated with a constant. Buttons, for example, typically send action messages on the UIControlEvents.touchUpInside control event. A target registered for this control event will only receive its action message if the user touches the control and then lifts the finger off the screen inside the frame of the control.

For a button, however, you can have actions on other event types. For example, you might trigger a method if the user removes the finger inside or outside the frame. Assigning the target and action programmatically would look like this:

button.addTarget(self,
    action: #selector(Thermostat.resetTemperature(_:)),
    for: [.touchUpInside, .touchUpOutside])

Now consider how UIControl handles UIControlEvents.touchUpInside.

// Not the exact code. There is a bit more going on!
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

    // Reference to the touch that is ending
    let touch = touches.first!

    // Location of that point in this control's coordinate system
    let touchLocation = touch.location(in: self)

    // Is that point still in my viewing bounds?
    if bounds.contains(touchLocation) {
        // Send out action messages to all targets registered for this event!
        sendActions(for: .touchUpInside)
    }
    else {
        // The touch ended outside the bounds: different control event
        sendActions(for: .touchUpOutside)
    }
}

So how do these actions get sent to the right target? At the end of the UIResponder method implementations, the control calls the method sendActions(for:) on itself. This method looks at all of the target-action pairs the control has. If any of them are registered for the control event passed as the argument, the corresponding action method is called on those targets.

However, a control never calls a method directly on its targets. Instead, it routes these method calls through the UIApplication object. Why not have controls call the action methods directly on the targets? Controls can also have nil-targeted actions. If a UIControl’s target is nil, the UIApplication finds the first responder of its UIWindow and calls the action method on it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset