Target-Action

在Selector篇章中提到了Target-Action这个概念:

Although delegation, bindings, and notification are useful for handling certain forms of communication between objects in a program, they are not particularly suitable for the most visible sort of communication. A typical application’s user interface consists of a number of graphical objects, and perhaps the most common of these objects are controls. A control is a graphical analog of a real-world or logical device (button, slider, checkboxes, and so on); as with a real-world control, such as a radio tuner, you use it to convey your intent to some system of which it is a part—that is, an application.

The role of a control on a user interface is simple: It interprets the intent of the user and instructs some other object to carry out that request. When a user acts on the control by, say, clicking it or pressing the Return key, the hardware device generates a raw event. The control accepts the event (as appropriately packaged for Cocoa) and translates it into an instruction that is specific to the application. However, events by themselves don't give much information about the user's intent; they merely tell you that the user clicked a mouse button or pressed a key. So some mechanism must be called upon to provide the translation between event and instruction. This mechanism is called target-action.

Cocoa uses the target-action mechanism for communication between a control and another object. This mechanism allows the control and, in OS X its cell or cells, to encapsulate the information necessary to send an application-specific instruction to the appropriate object. The receiving object—typically an instance of a custom class—is called the target. The action is the message that the control sends to the target. The object that is interested in the user event—the target—is the one that imparts significance to it, and this significance is usually reflected in the name it gives to the action.

尽管代理,绑定和通知对于解决处理在程序中确切的交流通讯非常有效,但是它们对于可视化的通讯结构不是非常合适。一个典型的应用程序界面包含了一系列图形对象,并且可能最寻常这些对象可能就是controls 控制器。一个控制器是一种真实世界上的或者逻辑设备上的图形式的类别(按钮,滑动条,复选框或者其他);作为一个真实世界的控制器,例如广播协调器,你使用它来传递你的内容给一些系统的部分 - 这就一个是应用。


控制器在用户界面的角色是非常简单的:它解析了用户的内容并且指示了一些其他对象来执行相关的请求。当一个用户在控制器发挥作用,例如讲述语音,点击Return按钮,硬件设备生成一行事件。控制器接受了事件(Cocoa已经合适地封装成包)并且将它转化成应用相应的指示。然而,关于它们的事件并没有给足够多的信息关于用户的内容;它们很少高速你用户点击鼠标按钮或者是按住了一个key。所以一些机制必须被调用来提供转换到事件和指令的信息。这种机制叫做 target-action  ! 这种机制也是一种设计模式!~~


Cocoa使用target-action来帮助控制器和其他对象的通讯。这个机制使得OS X它的单元上能够封装必须的信息来发送一些特定应用的指令给合适的对象。接受对象-通常是一个自定义类的实例对象-被称作target。action就是一个消息,这个消息是控制器发送给target的。对于用户事件非常感兴趣的对象- 通常是target - 是一个被赋予的意义,并且这个意义是被用来反映到分配到action的名字。



Target-action is a design pattern in which an object holds the information necessary to send a message to another object when an event occurs. The stored information consists of two items of data: an action selector, which identifies the method to be invoked, and a target, which is the object to receive the message. The message sent when the event occurs is called an action message. Although the target can be any object, even a framework object, it is typically a custom controller that handles the action message in an application-specific way.

Target-action 是一种设计模式,这种设计模式拥有一些必须的信息来发送消息给另外的一些对象当事件发生的时候。保存的信息由两种类型的数据组成:一个是action选择器,这标记了要被调用的方法,另外一个是target,是用来接收消息的对象。消息被发送当事件被一个action消息调用的时候。尽管target能是任意的对象,甚至一个framework对象,但是它总是一个自定义的控制器,这个控制器处理了action消息用一种应用上特定的方式。


对这一段官网的定义和上图的演示,可以用一个很经典的例子:


addTarget : 通常为 self,就是将视图控制器作为Target对象, action: 用选择器@selector 来获取action方法, 而驱动这个target-action的event 通常就是点击。


The event triggering an action message can be anything, just as the object sending the message can be any object. For example, a gesture-recognizer object might send an action message to another object when it recognizes its gesture. However, the target-action paradigm is most commonly found with controls such as buttons and sliders. When a user manipulates a control object, it sends the message to the specified object. The control object is an instance of a subclass of UIControl (iOS) or NSControl/a (OS X). Both action selector and target object are properties of a control object or, in the AppKit framework, properties of the control’s cell object.

所触发action消息发送的事件可以是任何东西,就如发送消息的对象可以是任何对象。例如,gesture-recognizer对象可能会发送一个action消息给其他对象当它辨认到这个手势之后。然而,target-action 的范式常常是被应用在按钮和滚动条这些类型。当一个用户操纵一个控制器对象,它发送一个消息给确定的对象。控制器对象是一个UIControl的实例或者是其子类的实例。action选择器和target对象都是control对象的属性。


通过上面文档的描述,相信对target-action 的机制其实还是非常模糊陌生的,我们继续对target/action这个神秘的东西剖析


The Target

A target is a receiver of an action message. A control or, more frequently, its cell holds the target of its action message as an outlet (see Outlets). The target usually is an instance of one of your custom classes, although it can be any Cocoa object whose class implements the appropriate action method.

Target是action消息的接受者。并且只要是实现了合适的action方法的任意对象。


The Action

An action is the message a control sends to the target or, from the perspective of the target, the method the target implements to respond to the action message. A control or—as is frequently the case in AppKit—a control’s cell stores an action as an instance variable of type SEL. SEL is an Objective-C data type used to specify the signature of a message. An action message must have a simple, distinct signature. The method it invokes returns nothing and usually has a sole parameter of type id. This parameter, by convention, is named sender. Here is an example from the NSResponder class, which defines a number of action methods:

提到的几点重要的信息:SEL是一种OC的数据类型,并且一个action消息必须是拥有一个简单的,可区分的签名signature。 The method it invokes returns nothing and usually has a sole parameter of type id. This parameter, by convention, is named sender. 这句话非常重要!解释了sender 由来!id类型的sender参数就是一种约定俗成的东西。

简单的例子:

- (void)capitalizeWord:(id)sender;


The sender parameter usually identifies the control sending the action message (although it can be another object substituted by the actual sender). The idea behind this is similar to a return address on a postcard. The target can query the sender for more information if it needs to. If the actual sending object substitutes another object as sender, you should treat that object in the same way. For example, say you have a text field and when the user enters text, the action method nameEntered: is invoked in the target:

sender参数通常用发送action消息来辨认控制器对象(尽管能用其他真实的sender来代替)。这种想法是和返回一个地址在postcard是一样道理的。target对象可以查询sender获取更多的信息如果需要的话。如果一个确定的发送对象代替了另外一个对象作为sender,你必须对待这个对象用相同的方式。例如:

- (void)nameEntered:(id) sender {
    NSString *name = [sender stringValue];
    if (![name isEqualToString:@""]) {
        NSMutableArray *names = [self nameList];
        [names addObject:name];
        [sender setStringValue:@""];
    }
}

重要的在于怎么处理sender!



总结:

Target-Action in UIKit

The UIKit framework also declares and implements a suite of control classes; the control classes in this framework inherit from the UIControl class, which defines most of the target-action mechanism for iOS. However there are some fundamental differences in how the AppKit and UIKit frameworks implement target-action. One of these differences is that UIKit does not have any true cell classes. Controls in UIKit do not rely upon their cells for target and action information.

UIKit框架也声明了一系列的control类型的实现;控制器类都是继承于UIControl类的,这定义了大多数iOS的target-action机制。我们接触的很多的例如按钮啊滚动条啊等等交互性很强的东西都是这套机制所提供的。


A larger difference in how the two frameworks implement target-action lies in the nature of the event model. In the AppKit framework, the user typically uses a mouse and keyboard to register events for handling by the system. These events—such as clicking on a button—are limited and discrete. Consequently, a control object in AppKit usually recognizes a single physical event as the trigger for the action it sends to its target. (In the case of buttons, this is a mouse-up event.) In iOS, the user’s fingers are what originate events instead of mouse clicks, mouse drags, or physical keystrokes. There can be more than one finger touching an object on the screen at one time, and these touches can even be going in different directions.

区别直接略了。


To account for this multitouch event model, UIKit declares a set of control-event constants in UIControl.h that specify various physical gestures that users can make on controls, such as lifting a finger from a control, dragging a finger into a control, and touching down within a text field. You can configure a control object so that it responds to one or more of these touch events by sending an action message to a target. Many of the control classes in UIKit are implemented to generate certain control events; for example, instances of the UISlider class generate a UIControlEventValueChanged control event, which you can use to send an action message to a target object.

为了说明多点触碰事件模型,UIKit声明了一系列的控制器事件约束项在UIControl.h,它分清楚了不同的物理手势,都是用户能够在控制器上做的操作,例如在控制器上的起重,和在text field类型的输入框里面按下的动作。你可以配置一个控制器对象以至于它能否对一个或多个触碰事件通过发送action消息给target。UIKit上大多数控制器的类都被实现来省城确定的控制器事件;例如,UISlider类生成了UIControlEventValueChanged控制事件,你可以利用这个来发送action消息给target对象。

这里的解释就清晰多了,UIKit的框架在UIControl类的target-action做了大量的工作,例如像UIButton的按下弹起的动作可以用事件类型:UIControlEventTouchUpInside  来控制。而 UISlide类就可以用:UIControlEventValueChanged 来控制。

这里提到的事件类型是定义在UIControl.h的一个枚举类型:

typedef NS_OPTIONS(NSUInteger, UIControlEvents) {
    UIControlEventTouchDown           = 1 <<  0,      // on all touch downs
    UIControlEventTouchDownRepeat     = 1 <<  1,      // on multiple touchdowns (tap count > 1)
    UIControlEventTouchDragInside     = 1 <<  2,
    UIControlEventTouchDragOutside    = 1 <<  3,
    UIControlEventTouchDragEnter      = 1 <<  4,
    UIControlEventTouchDragExit       = 1 <<  5,
    UIControlEventTouchUpInside       = 1 <<  6,
    UIControlEventTouchUpOutside      = 1 <<  7,
    UIControlEventTouchCancel         = 1 <<  8,

    UIControlEventValueChanged        = 1 << 12,     // sliders, etc.

    UIControlEventEditingDidBegin     = 1 << 16,     // UITextField
    UIControlEventEditingChanged      = 1 << 17,
    UIControlEventEditingDidEnd       = 1 << 18,
    UIControlEventEditingDidEndOnExit = 1 << 19,     // 'return key' ending editing

    UIControlEventAllTouchEvents      = 0x00000FFF,  // for touch events
    UIControlEventAllEditingEvents    = 0x000F0000,  // for UITextField
    UIControlEventApplicationReserved = 0x0F000000,  // range available for application use
    UIControlEventSystemReserved      = 0xF0000000,  // range reserved for internal framework use
    UIControlEventAllEvents           = 0xFFFFFFFF
};

其实只要理解,iOS体系的event机制,responder机制,再来理解target-action难度就不大了。


You set up a control so that it sends an action message to a target object by associating both target and action with one or more control events. To do this, send addTarget:action:forControlEvents: to the control for each target-action pair you want to specify. When the user touches the control in a designated fashion, the control forwards the action message to the global UIApplication object in a sendAction:to:from:forEvent: message. As in AppKit, the global application object is the centralized dispatch point for action messages. If the control specifies a nil target for an action message, the application queries objects in the responder chain until it finds one that is willing to handle the action message—that is, one implementing a method corresponding to the action selector.

你设置一个控制器用来发送一个action消息给target对象通过用一个或多个events事件来联系target和action。可以用UIControl类的方法addTarget:action:forControlEvents:来确认每一对target-action。当用户触碰控制器类用一个特定的方式,控制器会通过UIApplication对象的sendAction:to:from:forEvent:消息来达到。如果控制器为action 消息不设置target或者设置target为nil,这个时候会利用响应链来寻找适当的action消息-即是,与这个action消息所关联的实现方法。

- (void)action		//既不设置sender,也不设置event事件,只存在action消息
- (void)action:(id)sender    //不设置event事件
- (void)action:(id)sender forEvent:(UIEvent *)event    //既有sender,也有event事件

在计时器也有相当相似的一些方法:

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;

用法和意义也非常好理解,只是添加了一些额外更具体的参数。




参考至:苹果官方文档



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值