iT邦幫忙

0

iOS SDK 學習筆記04:淺談 Target-Action

  • 分享至 

  • xImage
  •  

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 分離,提升程式碼的可維護性。


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言