游乐游手机版
首页/编程语言/文章详情

iOS设计模式之委托模式核心原理与实战解析

时间:2026-06-14 06:48
CocoaTouch框架中大量使用委托模式,通过协议和id类型实现对象间的单向协作。委托模式与适配器模式高度相似,充当对象间的转换器。实现方式包括传统协议和Block,协议适合多次回调,Block适合一次性场景。

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 更适合一次性回调的场景——例如网络请求完成后执行的代码。而传统的委托则更适合需要多次回调、或者需要区分多个回调方法的情况。两者各有适用的场景,具体选择哪种方式取决于实际需求。

来源:https://www.jb51.net/article/278700.htm
上一篇iOS KeyChain数据持久化操作详解 下一篇iOS组件化开发初步思路分析
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
AWS RDS 数据库配置入门与基础操作指南
编程语言 · 2026-07-10

AWS RDS 数据库配置入门与基础操作指南

本文介绍了AWSRDS的基本概念与核心价值,即提供托管式关系数据库服务,简化运维。详细阐述了创建RDS实例的关键配置步骤,包括引擎选择、实例规格、存储与网络设置。最后,指导读者如何通过多种方式安全连接至数据库实例,并开始进行数据操作,为后续应用开发奠定基础。

PHP MVC中AJAX请求无法调用控制器方法的原因与解决方案
编程语言 · 2026-07-10

PHP MVC中AJAX请求无法调用控制器方法的原因与解决方案

PHPMVC中AJAX请求返回整页HTML的常见原因是控制器方法未正确输出响应或未终止执行,导致框架渲染视图。解决方法是在控制器中设置JSON响应头、输出数据后调用exit()明确终止,同时前端使用小写url和dataType: "json "。

Go语言手动构造rsa.PublicKey:正确初始化大整数模数N完整指南
编程语言 · 2026-07-10

Go语言手动构造rsa.PublicKey:正确初始化大整数模数N完整指南

手动构造RSA公钥时,模数N为*big Int类型,不能直接使用超长十进制字面量,需通过SetString或UnmarshalText方法解析字符串。公钥指数E可直接赋值,推荐65537。生产环境应使用rsa GenerateKey生成密钥对,避免手动构造引发的安全和格式错误。

Go语言实现HTTP定时轮询监控多URL响应时间与状态检测
编程语言 · 2026-07-10

Go语言实现HTTP定时轮询监控多URL响应时间与状态检测

使用Go语言实现HTTP定时轮询监控,通过按行分割与Tab解析URL列表,避免闭包陷阱和nil指针,每个URL启动独立ticker安全并发请求,并配置超时控制与资源关闭,确保响应时间与状态码准确检测。

Tkinter中Label标签在主循环动态更新的正确方法
编程语言 · 2026-07-10

Tkinter中Label标签在主循环动态更新的正确方法

在Tkinter中正确动态更新标签的方法:将标签组件的textvariable参数绑定到一个StringVar变量,然后通过调用该变量的 set()方法更新其值,界面会自动刷新。这样避免直接修改text属性或调用update()。此做法实现数据与界面的解耦,代码更简洁,响应更及时,避免手动同步的闪烁,推荐做法。