delegate 若對C語言比較熟,其目的有點像是 function pointer。
在 C語言寫作時,我們為了要撰寫 像是
1. call back function,亦即執行某個程式,而在程式結束之後,自動返回。
2. 在compile期間,尚不知道會給哪個 function進行。
參考developer.apple.com的說明
Delegation is a simple and powerful pattern in which one object in a program acts on behalf of, or in coordination with, another object.The delegating object keeps a reference to the other object—the delegate—and at the appropriate time sends a message to it. The message informs the delegate of an event that the delegating object is about to handle or has just handled. The delegate may respond to the message by updating the appearance or state of itself or other objects in the application, and in some cases it can return a value that affects how an impending event is handled. The main value of delegation is that it allows you to easily customize the behavior of several objects in one central object.換言之,這就像是 我知道 要完成一個任務,需要a技能,而 "小寶" 他有a技能,那麼我就delegate給小寶,並在需要的時候,委由小寶幫我執行。
因此像底下的例子 HelloAppDelegate 有<UIApplicationDelegate>
HelloAppDelegate 就需要處理 applicationDidFinishLaunching、applicationWillTerminate、applicationDidReceiveMemoryWarning....等。
物件中 has a的關係在大部份的Design Pattern書籍中,將之說成Delegate(委派)。
設計類別時,在一般情況下應儘量使用委派(delegate)而少用繼承。
以委派取代繼承的時機:某個subclass只使用super classes 介面中的一部份,或是根本沒用到繼承而來的資料。
以繼承取代委派的時機:當在二個classes中使用delegate,並經常為二個classes間寫作許多簡單的delegate function。
(資料來源: http://blog.joomla.org.tw/iphone-ipad/112-delegate-controller1.html )
這一陣子學了不少的應用和實作許多相關的開發學習範例。最近最有疑問的是有關於Delegate(委託)和Controller(控制者)的相關性,這兩個看起來似乎很像,但又有些不同。找了不少相關的資料之後,大致上有了一些結論,把它整理到這裡。
Delegate實際上也是一種Design Pattern(設計模式),在官方的文件中,有很清楚的說明這個的運作過程:
The delegating object is typically a framework object, and the delegate is typically a custom controller object. The delegating object holds a weak reference to its delegate.
"進行委託的"物件(稱為host object)基本上是一個框架物件,而"委託代表"是基本上是一個自訂的控制者物件。進行委託的物件維繫一個弱的參考到它的代表。
在上述文件的例子中,使用者在視窗上點下關閉的按鈕,視窗會送出一個訊息給委託代表,由委託代表負責回應是不是可以關閉這個視窗。這是一個最簡單的委託的例子。
文件在接下來的說明又談到另一個設計模式,稱為Observer(觀察者)模式,委託和notification(通知)之間的關係在於,委託代表在Cocoa中會自動成為訊息的觀察者,訊息會在事件發生之後產生,用廣播的方式通知所有的觀察者,這是這個模式的主要實作的用途。
至於最後一項稱為data source(資料源),字義上看起來似乎是MVC中的Model部份,實際並不是,它也是一種委託代表,和上述的委託代表不同處,在於委託它的物件,從上述的UI(使用者操作介面),換成了資料。
委託在實作的部份,都是透過protocol(協定)的方式,Objective-C的protocol的行為類似Java中interface。在Cocoa中,可以在NSApplication, UIApplication, UITableView, 和NSView的子類別中看到委託的設計。以下是有關於iPhone OS的委託說明:
The application delegate is extremely important in an application running on iPhone OS, as it must respond to application-launch, application-quit, low-memory, and other messages from the application object. The application delegate must adopt the UIApplicationDelegate protocol.
在iPhone OS上執行的應用程式中應用程式委託是非常重要的,因為它需要回應程式的開始執行、程式關閉、低記憶體及其他從程式物件中發出的訊息。應用程式委託需要採用UIApplicationDelegate協定。
當然目前我所接觸到的,最常見的只有這個UIApplicationDelegate,在每個iPhone的應用程式都可以看到一個委託的檔案,例如在最基本的Hello範例中:
HelloAppDelegate.h | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #import <UIKit/UIKit.h> @class HelloViewController; //START:code.HelloAppDelegate.interface @interface HelloAppDelegate : NSObject <UIApplicationDelegate> { IBOutlet UIWindow *window; IBOutlet HelloViewController *viewController; } @property (nonatomic, retain) UIWindow *window; @property (nonatomic, retain) HelloViewController *viewController; @end |
- 「applicationDidFinishLaunching:」程式啟動完成後通知,這裡通常會加入應用程式的初始化的工作
- 「applicationWillTerminate:」程式結束前通知,結束前應作好重要設定或資料的儲存,例如遊戲應儲存目前的狀態,下次才能從這個狀態再繼續。
- 「applicationDidReceiveMemoryWarning:」程式收到系統通知記憶體警告,如果收到警告後不釋放足夠的記憶體,系統將會強制中止程式。(註:之類後會談到UIViewController中的didReceiveMemoryWarning方法,類似功用 )
- 「applicationWillResignActive:」程式將進入無效狀態通知,系統收到郵件或來電時、iPhone上鎖的通知,程式委託將不再接受任何的互動操作。程式要在此作一些暫時停止運作的工作。
- 「applicationDidBecomeActive:」程式將回復原本的有效狀態,並繼續原來的工作。
委託在許屬控制元件中很常見,例如在使用UIWebView、UIPickerView、UITableView、UITextField這些控制元件時,也有自己對應的UIWebViewDelegate、UIPickerViewDelegate、UITableViewDelegate、UITextFieldDelegate協定,那倒底有那些控製元件有對應的委託協定?這份表中的Protocol References列出了所有UIKit系列的委託和資料源協定。
總結一下委託的機制用法,委託即是會自動收到在某些應用程式事件發生時的通知,在這些事件發生時的前或後,可以讓你作一些工作。
上一篇談到有關於Delegate的概念,那Delegate和Controller又有什麼關係?先了解所謂的MVC設計模式,就可以很清楚的了解Controller的意義是什麼了,以下是一張來自官方文件Controller object的解說圖片:

在這篇文件中,雖然區分出了三種控制者物件,但特別有指出在iPhone OS中,View Controllers(視圖控制器)就是扮演Coordinating Controllers(協調控制器)的角色,協調控制器的功能如下:
而視圖控制器的其他說明如下(這段有點長 @@"我去掉了一些):
透過理解控制器的功能之後,先看一下最常接觸到的UIViewController中的可用方法有那些:
這些只有列出常見的,詳細的方法可以在這個文件中找到。看到了嗎?這些收到訊息後或前執行的方法,都和視圖有關,可以說視圖控制器主要是用來管理和控制視圖的。執行熟悉了UIViewController之後,剩下的像繼承自這個類別的子類別有三大個:有UITableViewController、UITabBarController、UINavigationController如果能熟悉各自的應用方法,大致上Controller部份就沒問題了。
了解嗎?還是有點模糊?我的理解是Controller是在於MVC設計模式中的C這個角色,扮演Model和View的居中協調者的工作。當然ViewController的工作就是針對視圖的控制器工作,管理視圖,例如在需要的時候載入它到記憶體中,不需要時在記憶體中釋放它。要記得在iPhone OS中,通常一個視圖只會有一個視圖控制器。
而Delegate/data source是另一種實作事件控制的模式,也是位於MVC中C這個位置的機制,只是因為它是利用協定而非一般的子類別繼承實體而來,變成另一類處理控制的機制。但是,這兩種並不會是衝突或只能擇一使用,在很多情況下,反而是兩種都要搭配使用才能完成所需的工作。

有關於Controller(控制器)的說明我把它摘錄在下面:
A controller object acts as a coordinator or as an intermediary between one or more view objects and one or more model objects. In the Model-View-Controller design pattern, a controller object (or, simply, a controller) interprets user actions and intentions made in view objects-such as when the user taps or clicks a button or enters text in a text field-and communicates new or changed data to the model objects.
控制器物件扮演一個或多個的view物件和一個或多個的model物件的的協調者或是媒介。在Model-View-Controller設計模式中,一個控制器元件翻譯了使用者對view物件的動作和意圖,例如使用者觸碰或按下按鈕,或是在文字欄位中輸入文字,會傳送新的或更動的資料到model物件。
在這篇文件中,雖然區分出了三種控制者物件,但特別有指出在iPhone OS中,View Controllers(視圖控制器)就是扮演Coordinating Controllers(協調控制器)的角色,協調控制器的功能如下:
- Responding to delegation messages and observing notifications
負責委託訊息和觀察通知 - Responding to action messages (which are are sent by controls such as buttons when users tap or click them)
負責動作訊息 - Establishing connections between objects and performing other setup tasks, such as when the application launches
建立物件間的連結,和執行其他設定的工作,例如程式開發執行的工作 - Managing the life cycle of “owned” objects
管理擁有物件的生命週期
而視圖控制器的其他說明如下(這段有點長 @@"我去掉了一些):
A view controller manages a full-screen view, which it keeps a reference to and may create or load from a nib file. The controller manages the presentation of this view and the next view ...The navigation bar and the tab bar, and all their associated presentation behavior, are managed and implemented by view controller objects. View controllers can also display modal views, respond to low-memory warnings, and rotate views when the orientation changes.
一個視圖控制器管理並維繫了一個參考到由nib檔案所建立或載入的一個全螢幕的視圖。控制器管理這個視圖呈現方式,以及下一個在使用者介面中要呈現的首要視圖。導覽列和分頁列,以及所有相關的呈現行為,都被視圖控制物件管理和實現。視圖控制器也可以顯示獨佔的視圖、回應低記憶體警告,以及當方向改變時旋轉視圖。
A view controller is an instance of a subclass of UIViewController. The UIKit provides several special-purpose subclasses of UIViewController, such as UITableViewController.... View controllers are typically the delegate or data source objects for many types of framework objects.
視圖控制器是一個UIViewController子類別的實體。UIKit提供了一些針對特別需求的UIViewController子類別,像是UITableViewController。視圖控制器基本上是針對於許多框架物件的委託或資料源物件。
透過理解控制器的功能之後,先看一下最常接觸到的UIViewController中的可用方法有那些:
- 「initWithNibName: bundle:」載入nib檔案來初始化
- 「loadView」載入視圖
- 「viewDidLoad」在載入視圖至記憶體後會呼叫的方法
- 「viewDidUnload」在視圖從記憶體中釋放後會呼叫的方法
- 「viewWillAppear」當收到視圖在視窗將可見時的通知會呼叫的方法
- 「viewWillDisappear」當收到視圖在視窗將不可見時的通知會呼叫的方法
- 「viewDidAppear」當收到視圖已加入到視窗時的通知會呼叫的方法
- 「viewDidDisappear」當收到視圖已去除、被覆蓋或隱藏於視窗時的通知會呼叫的方法
- 「didReceiveMemoryWarning」收到系統傳來的記憶體警告通知後會執行的方法
- 「shouldAutorotateToInterfaceOrientation」是否支援不同方向的旋轉視圖
- 「willAnimateRotationToInterfaceOrientation」在進行旋轉視圖前的會執行的方法(用於調整旋轉視圖之用)
這些只有列出常見的,詳細的方法可以在這個文件中找到。看到了嗎?這些收到訊息後或前執行的方法,都和視圖有關,可以說視圖控制器主要是用來管理和控制視圖的。執行熟悉了UIViewController之後,剩下的像繼承自這個類別的子類別有三大個:有UITableViewController、UITabBarController、UINavigationController如果能熟悉各自的應用方法,大致上Controller部份就沒問題了。
最後要談到最前面的問題:那Delegate和Controller又有什麼關係?有何不同,我在stackoverflow找到覺得比較好的說明:
A delegate is a protocol (interface) that defines methods that an object implements in order to receive specific messages from other objects. Delegates objects are most often used to receive asynchronous callbacks such as user input, I/O.
委記是一個協定(介面),定義了許多物件可以實作的方法,為了接收來自其他物件的特定訊息。委託物件經常使用於接收非同步的回應呼叫,例如使用者輸入或I/O。
A controller is an object that usually contains UI elements (views, controls, etc.) and data, and both receives and send messages to the various objects within it. In many cases, a controller is a delegate and can implement several delegate protocols to receive events from multiple objects.
控制器是一個物件,通常其中包含UI元素(視圖、控制器…等)和資料,以及接收和傳送兩種訊息到其中的眾多物件。在大部份時候,控制器是一個委託且可以實作各種委託協定,以便可以接收來自多個物件的事件。
而Delegate/data source是另一種實作事件控制的模式,也是位於MVC中C這個位置的機制,只是因為它是利用協定而非一般的子類別繼承實體而來,變成另一類處理控制的機制。但是,這兩種並不會是衝突或只能擇一使用,在很多情況下,反而是兩種都要搭配使用才能完成所需的工作。