iOS SDK 学习笔记04:浅谈 Target-Action

What is Target-Action?

整理一下目前我对 target-action 的理解:

让我们先来看落落长的定义

The term target–action design paradigm refers to a kind of software architecture, where a computer program is divided into objects which dynamically establish relationships by telling each other which object they should target and what action or message to send to that target when an event occurs. This is especially useful when implementing graphical user interfaces, which are by nature event-driven. — From Wikipedia

target-action 是一种软体架构的设计模式,将程式分成很多个 objects,这些 objects 透过告知它们应该以哪个对象为目标以及在事件发生时向该目标发送什么动作或消息来动态建立关係 . 这在实现本质上是事件驱动的图形用户界面时特别有用。

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. — From Apple Documentation

Target-action 是一种设计模式,其中一个物件在事件发生时,保留传送讯息给另一个物件所需的资讯。这些资讯包括两个项目:一个动作选择器 (action selector),用于识别要呼叫的方法,以及一个目标物件(target),用于接收讯息。当事件发生时传送的讯息称为动作讯息 (action message)。目标物件可以是任何物件,甚至是框架物件,但通常是处理应用程式特定方式的自订控制器。


以上资料分别截取自维基百科以及苹果官方文件,让我们不要咬文嚼字,改用以下例子来理解。

example1

以上是一段简单的 Swift 程式码,用 class 宣告了 Door 这个物件,并且定义了一个 method open() 后,并依此建立一个 door 实例,并呼叫方法。这段程式码遵循了 OOP 的基本原则,透过将功能封装在 class 里,实现了封装性 (Encapsulation) 这个特性。

然而若将场景拉到 iOS app 上来看,例如下图:

example2

以上是在 iOS 开发中最基本的功能之一,也就是让使用者点击某个 button 后,画面上的 label 会随之改变。
但看似简单的功能,实际上涉及了:

撰写追蹤使用者触碰手机萤幕的程式码判断是否是目标控制元件所属的 touch 事件决定要执行哪些方法

对于开发者而言所需着重之部分应为最后一点,即决定在发生何种事件后,要实现什么样的逻辑,来回应使用者的行为及期待。
其余部分,则由 iOS 替你处理,让开发者可以专注于处理事件处理,如以下苹果官方的示意图:

example3


The simplest approach

example4

在我们最一开始学习开发 iOS 时,如果你是从 UIKit 开始学习,通常都会从 Storyboard 拉元件开始。透过拉取一个 @IBAction function 到程式码中,并在 function 中定义你要实作的行为。事实上这就是一种 target-action mechanism 的展现。

但我们有另外一种方法可以达到相同的效果:

example5

根据苹果官方定义,你可以呼叫 addTarget(_:action:for:) 此 function 来替你的元件加入特定事件。

target: 在哪做 (The object whose action method is called)action: 做什么controlEvents: 在什么情况下触发

因此我们可以改用下列方法来实作:

example6

不论是直接拉 @IBAction 或使用 addTarget(_:action:for:) 此种方式皆可达到元件与 action 分离解耦之效。

target

The target object—that is, the object whose action method is called. If you specify nil, UIKit searches the responder chain for an object that responds to the specified action message and delivers the message to that object.

根据官方文档,target 如果被设置为 nil,UIKit 会在 responder chain 中查找能够响应指定动作消息的 object,并将 action 传递给该 object 进行处理。以上图来说,我们带入 target 的参数为 self,即所在的 ViewController。

在 iOS 中,responder chain 用于处理事件和响应使用者的操作。当事件发生时,UIKit 会沿着 responder chain 向上查找第一个能够响应该事件的对象,并将事件传递给其 action 进行处理。

example6
example7

可以看到当 target 参数设为 nil 时,仍能正确呼叫到 sayHi() 这个 function。

example8
Responder chain 参考示意图

selector

Selector 这个参数,官方列举了三种形式:

example9

doSomething():没有任何参数。doSomething(sender: UIButton):这个方法接受一个 UIButton 类型的参数,它表示发生事件的按钮对象。你可以通过这个参数来判断是哪个按钮触发了事件。doSomething(sender: UIButton, forEvent event: UIEvent):这个方法接受两个参数: UIButton 类型的 sender 和 UIEvent 类型的 event。 sender 参数表示发生事件的按钮对象,event 参数则包含了更多关于事件的讯息,例如事件的 timestamp、触碰坐标、触碰次数等。

event

侦测什么样的事件,例如我们最常使用的 .touchUpInside,其余可 可参考官方文档。

小结

使用 target-action 可以让开发者可以专注于处理事件,决定使用者流程,并可使控制元件与 action 分离,提升程式码的可维护性。


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章