Cocoa Touch 框架在 iOS 开发中大量采用了委托(Delegation)这一设计模式。根据苹果官方的定义,delegate 就是委托模式在 iOS 环境下的具体实现形式——简单来说,它是一种让对象之间实现“单向通信”的协作机制。
为了真正掌握委托的核心原理,我们需要先理清几个基本概念。下面就从最基础的协议开始讲起。
(一)协议
在 Objective-C 中,协议对于熟悉 C++ 或 Java 的开发者而言,可以类比为抽象类或接口。协议只声明方法,不负责具体实现。其定义格式如下:
@protocol MyButtonDelegate@optional - (void) didPressButton; @end
其中 @protocol 是关键字,MyButtonDelegate 是协议名称,didPressButton 就是协议中声明的方法。注意这里使用了 @optional,表示该方法并非强制实现——这恰恰体现了委托模式的灵活性与扩展性。
(二)id 类型
id 是 Objective-C 中一个非常特殊的类型,它可以被视为一个能够指向任意对象的通用指针。它的底层定义如下:
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
换句话说,任何 Objective-C 对象本质上都是一个 objc_object 结构体,而 id 就是指向这个结构体的指针。正因为它可以指向任意类型的对象,所以委托对象通常被声明为 id 类型,这样调用方就无需关心具体是哪个对象实现了协议中的方法。
(三)适配器模式
在经典的设计模式分类中,并没有一个独立的“委托模式”。但仔细观察会发现,委托所做的工作与适配器模式高度相似。举一个生活中的例子:去香港出差时,发现笔记本电脑的插头无法插入墙上的插座——因为香港使用的是英式三脚插头。这时你需要一个转换器,先把插头转换成能插入的形状,然后才能正常通电。委托模式在很多场景下恰恰充当了这个“转换器”的角色,它让两个原本没有直接关联的对象能够协同工作,本质上实现了一种对象适配器。
(四)实例
现在我们动手编写一个自定义按钮组件,其功能与 UIButton 类似,但使用委托来通知点击事件。首先从 UIView 继承一个 MyButton 类。问题是:我们并不清楚未来谁会使用这个按钮,但可以确定的是,每个使用者都需要在按钮被按下时收到通知。也就是说,MyButton 需要向某个对象(Adaptee)发送“我被按下了”的消息。
适配过程的设计如下:
@protocol MyButtonDelegate@optional - (void) didPressButton; @end
这里的 MyButton 扮演了 Adapter 角色,它通过以下机制来调用 Adaptee 的方法:

图中的 Adaptee 可以是任意对象,只要它遵守了 MyButtonDelegate 协议。目前最常见的做法是将 RootViewController 作为 Adaptee,让它实现 didPressButton 方法,这样按钮点击时就能直接回调到控制器层面。
(五)委托模式的深入理解
除了传统的协议方式,委托模式还可以通过 Block 来实现。但需要注意的是,Block 更适合一次性回调的场景——例如网络请求完成后执行的代码。而传统的委托则更适合需要多次回调、或者需要区分多个回调方法的情况。两者各有适用的场景,具体选择哪种方式取决于实际需求。
