iOS – 委托(Delegates)(长文讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
前言
在 iOS 开发中,委托(Delegates) 是一种核心设计模式,广泛应用于系统框架和自定义功能中。它通过协议(Protocol)和回调机制,实现了对象间高效、灵活的通信。对于编程初学者来说,委托模式可能显得抽象难懂;而对于中级开发者,则需要掌握其进阶用法和最佳实践。本文将从基础概念逐步深入,结合代码示例和实际场景,帮助读者全面理解委托模式的原理与应用。
委托模式的定义与核心思想
什么是委托?
委托(Delegate)是一种对象间协作的编程模式,允许一个对象(委托对象)将某些任务或决策委托给另一个对象(委托代理)。
- 核心概念:
- 委托对象(Delegator):需要执行任务或获取信息的对象。
- 委托代理(Delegate):接收委托并提供具体实现的对象。
- 协议(Protocol):定义委托代理需要实现的方法或属性。
为什么需要委托?
委托模式通过解耦对象间的直接依赖,实现了代码的复用和扩展性。例如,UIKit 中的 UITableView
通过委托协议 UITableViewDelegate
,让外部对象负责数据源管理和交互逻辑,而非自己硬编码这些逻辑。
形象比喻:委托就像“中介”
想象一个快递代收点:快递公司(委托对象)将包裹的签收工作委托给代收点(委托代理)。快递公司无需关心代收点的具体操作,只需遵循协议(如“签收后返回回执”)。这种分工使双方职责清晰,系统更灵活。
委托模式的实现步骤
1. 定义协议(Protocol)
协议是委托的基础,它声明了委托代理需要实现的方法或属性。
protocol NetworkDelegate: AnyObject {
func didReceive(response: String)
func didFailWithError(error: Error)
}
2. 在委托对象中声明委托属性
委托对象需持有委托代理的弱引用(weak
),避免循环引用。
class NetworkManager {
weak var delegate: NetworkDelegate?
// ...
}
3. 实现委托方法
委托代理需遵守协议,并实现协议中定义的方法。
class ViewController: UIViewController, NetworkDelegate {
func didReceive(response: String) {
print("Received response: \(response)")
}
func didFailWithError(error: Error) {
print("Error: \(error.localizedDescription)")
}
}
4. 触发委托方法
当委托对象需要通知代理时,直接调用协议方法。
// 在 NetworkManager 中调用
delegate?.didReceive(response: "Success!")
实战案例:UITableView 的委托模式
案例背景
UITableView
的核心功能依赖于两个协议:UITableViewDataSource
和 UITableViewDelegate
。通过委托模式,开发者可以灵活控制表格的行数、单元格样式和交互行为。
实现步骤
1. 遵守协议并设置委托
在视图控制器中声明遵守协议,并将表格的委托属性指向自身。
class TableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
}
2. 实现数据源方法
通过 UITableViewDataSource
协议,定义表格的数据逻辑。
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10 // 返回行数
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "Row \(indexPath.row)"
return cell
}
3. 实现委托方法
通过 UITableViewDelegate
协议,定义单元格的交互行为,例如点击事件。
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Selected row \(indexPath.row)")
tableView.deselectRow(at: indexPath, animated: true)
}
案例总结
通过委托模式,UITableView
将数据展示和交互逻辑的控制权交给外部对象(如视图控制器),既保证了组件的通用性,又提高了代码的可维护性。
进阶技巧与常见问题
1. 强引用与弱引用的陷阱
委托属性必须使用 weak
关键字,否则会导致循环引用。例如:
// 错误写法:强引用导致内存泄漏
var delegate: NetworkDelegate! // 避免使用强引用
// 正确写法
weak var delegate: NetworkDelegate?
2. 可选方法与必需方法
在协议中,可以通过 @optional
和 @required
标记方法的可选性。但在 Swift 中,默认所有方法均为必需,需通过 @objc optional
标记可选方法(仅适用于 @objc
协议)。
@objc protocol CustomDelegate {
func requiredMethod()
@objc optional func optionalMethod()
}
3. 多个委托的处理
若一个对象需要同时遵循多个协议,可使用协议组合:
protocol DelegateA { ... }
protocol DelegateB { ... }
class MyClass: DelegateA, DelegateB { ... }
委托模式的扩展与最佳实践
1. 自定义委托场景
在自定义类中实现委托模式,例如创建一个网络请求工具类:
protocol NetworkServiceDelegate: AnyObject {
func didFinishLoading(data: Data)
}
class NetworkService {
weak var delegate: NetworkServiceDelegate?
func fetchData() {
// 模拟网络请求
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.delegate?.didFinishLoading(data: Data())
}
}
}
2. 使用闭包替代委托
对于简单场景,闭包(Closure)可能比委托更简洁。但委托更适合复杂或长期交互的场景。
class NetworkService {
var completionHandler: ((Data) -> Void)?
func fetchData(completion: ((Data) -> Void)?) {
completionHandler = completion
// ...
completionHandler?(Data())
}
}
3. 遵循 Apple 的设计规范
- 协议名称以
Delegate
结尾,如UITableViewDelegate
。 - 方法名以
delegate
开头,明确传递上下文对象(如tableView(_:didSelectRowAt:)
)。
结论
iOS – 委托(Delegates) 是 iOS 开发中不可或缺的设计模式,它通过协议和回调机制,实现了对象间松耦合、高扩展的通信。无论是系统框架如 UITableView
,还是自定义功能如网络请求,委托模式都能帮助开发者编写更清晰、可维护的代码。
通过本文的学习,读者应能掌握委托模式的实现原理、常见问题及最佳实践。在实际开发中,建议结合具体场景灵活运用委托模式,同时注意内存管理和协议设计的规范性,以提升代码质量和开发效率。
关键词布局:iOS – 委托(Delegates)、委托模式、协议、委托代理、回调机制、UITableViewDelegate、弱引用、闭包替代委托、内存泄漏、协议组合