在 Swift 中,delegate(代理)是一种常见的设计模式,广泛用于 UIKit 和其他框架。它允许一个对象将某些功能或决策委托给另一个对象,而不需要强耦合。这种模式通常通过 协议(protocol)来实现。
其基本机构如下:
-
协议(protocol) :定义了代理对象需要实现的方法。
-
委托对象(delegator) :它拥有一个代理属性,并在合适的时机调用代理方法。
-
代理对象(delegate) :实现协议中的方法,并在需要时响应委托对象的回调。
假设我们有一个 DownloadManager 类,它负责下载任务。通过代理模式,我们可以让 DownloadManager 通知其他类下载的进度或完成状态。
1. 定义协议:
protocol DownloadManagerDelegate: AnyObject {
func downloadDidFinish()
func downloadDidFail(withError error: Error)
}
这里我们定义了 DownloadManagerDelegate 协议,包含了两个方法,一个是下载成功的回调,另一个是下载失败的回调。使用 AnyObject 表示只有类可以作为代理。
2. 定义委托对象:
class DownloadManager {
weak var delegate: DownloadManagerDelegate?
func startDownload() {
// 模拟下载任务
let success = true // 假设下载成功
if success {
delegate?.downloadDidFinish()
} else {
let error = NSError(domain: "DownloadError", code: 1, userInfo: nil)
delegate?.downloadDidFail(withError: error)
}
}
}
在 DownloadManager 中,我们声明了一个 delegate 属性,并且它是弱引用(weak),避免循环引用。我们在下载完成后,调用代理方法来通知下载结果。
3. 实现代理对象:
class ViewController: UIViewController, DownloadManagerDelegate {
let downloadManager = DownloadManager()
override func viewDidLoad() {
super.viewDidLoad()
downloadManager.delegate = self
downloadManager.startDownload()
}
func downloadDidFinish() {
print("Download finished!")
}
func downloadDidFail(withError error: Error) {
print("Download failed with error: (error)")
}
}
在 ViewController 中实现 DownloadManagerDelegate 协议,并且将自身设置为 DownloadManager 的代理。这样,当下载完成或失败时,会调用相应的代理方法。
关键点:
-
弱引用(weak) :通常在委托对象中,代理是用
weak声明的,防止产生强引用循环。 -
解耦:代理模式让两个类之间通过协议通信,减少了类之间的耦合,使得代码更灵活和可维护。
-
回调:代理常用于回调操作,如异步任务的结果通知、事件的处理等。
应用场景:
-
UITableViewDelegate 和 UITableViewDataSource:用于处理表格视图的事件和数据源。
-
UITextFieldDelegate:用于处理文本输入事件。
-
自定义视图或控制器的 回调:如上例中的
DownloadManagerDelegate。
代理模式的优点就是为对象间的通信提供了灵活、松耦合的解决方案。