从其他平台来看Objective-C 的Delegate
Delegate 算是入门Objective-C的另外一个障碍,但了解之后就会知道其实很简单,一开始可能觉得并不好懂的主要原因是,delegate的这套作法,跟其他平台在做同样的事情的时候,作法比较不一样。
如果你曾经在其他的平台上开发过应用程序,像是微软的.Net平台的话,可以发现,在C#语言中在讲一个class有哪些成员的时候,会包括properties、 methods以及events;但是我们在讲Objective-C的class时,并不会提到events,C#中使用events在做的事情,在Objective-C中,我们往往使用target/action与delegate实作。1
虽然在Mac OS X与iOS上分别有NSEvent
与UIEvent
,但是这边的events与.Net里头讲的events又是两件事情:NSEvent
是用来描述键盘按了哪个按键,滑鼠移到了什么位置,而UIEvent
则用来描述触控事件以及耳机上的播放控制按钮等等,单纯用来描述从硬件输入了什么事件,透过操作系统传到我们的应用程序中。而C#里头所称的events,则是用来处理callback。
所谓callback 是指,当我们调用了一个function 或method之后,可能会花上许多时间,或是计算的是大量资料,或是需要透过网路连线,所以我们并不马上要求得到回传的结果,而是等到一段时间之后,计算结果才会透过另外一个function/method 传回来。
现在绝大多数的应用程序开发环境都采用MVC架构,我们将实例分成三类: model、view、controller,虽然在不同的平台上往往实现出来的结果不太一样,像是在微软的平台上,往往把window (或是form)当做是controller 使用,由window实例负责管理放在这个window 上面所有的control 元件,但是Mac OS X 上面window 并不拿来当做controller,而是被当成view,controller 在window之外,而且一个controller 也可以控制多个window…但都大抵如此。
在MVC 的架构中,我们通常会先建好controller class,然后加入model 与view,变成controller 的成员变量;因为model 与view 是controller的成员变量,所以controller 可以直接调用model 与view,那么,当model与view 发生了变化,要回来通知controller,我们也可以称之为callback,例如, controller建立了一个按钮,但是直到按钮被点选之后,controller 才负责做事。
在C# 中,我们要处理一个event,就要提供一个event handler,我们现在要处理的是Click:
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.button1.Click += Button1_Click;
}
private void Button1_Click(object sender, System.EventArgs e)
{
}
如果只是单纯的点选事件的话,我们会用target/action 实现。但,对照.Net framework 里头,events 不只是click 而已,还可能会有double click、 triple click、quadruple click…,如果是C# 里头,会这么写:
this.button1.Click += Button1_Click;
this.button1.DoubleClick += Button1_DoubleClick;
this.button1.TripleClick += Button1_TripleClick;
this.button1.QuadrupleClick += Button1_QuadrupleClick;
变成Objective-C 的话就可能变成:
[button1 setTarget:self];
[button1 setAction:@selector(click:)];
[button1 setDoubleTarget:self];
[button1 setDoubleAction:@selector(doubleClick:)];
[button1 setTripleTarget:self];
[button1 setTripleAction:@selector(tripleClick:)];
[button1 setQuadrupleTarget:self];
[button1 setQuadrupleAction:@selector(QuadrupleClick:)];
这样写起来实在很让人烦躁(虽然NSTableView
也的确有setDoubleAction:
…),所以,当这样的东西一多,在Objective-C语言里头,会直接准备好一个实例,这个实例准备好了所有可以调用的method,这个实例就叫做delegate,而这些可以调用的method的集合,叫做protocol。准备好这个实例之后,我们就不用调用这么多setDoubleAction:
、setTripleAction:
,只要调用setDelegate:
。
1 .我在写这章的时候,一直在想拿C#到底是不是好主意,毕竟想要学Objective-C语言者,不见得都有C#的基础。 之所以以C#举例,原因是这份资料其实是来自于当初我个人在公司内部的教材,而公司当时进来的新人之前是写C#的。 ↩