Swift知识碎片: 在Swift中如何创建使用Delegate代理

775 阅读2分钟

在 Swift 中,delegate(代理)是一种常见的设计模式,广泛用于 UIKit 和其他框架。它允许一个对象将某些功能或决策委托给另一个对象,而不需要强耦合。这种模式通常通过 协议(protocol)来实现。

其基本机构如下:

  1. 协议(protocol) :定义了代理对象需要实现的方法。

  2. 委托对象(delegator) :它拥有一个代理属性,并在合适的时机调用代理方法。

  3. 代理对象(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 声明的,防止产生强引用循环。

  • 解耦:代理模式让两个类之间通过协议通信,减少了类之间的耦合,使得代码更灵活和可维护。

  • 回调:代理常用于回调操作,如异步任务的结果通知、事件的处理等。

应用场景:

  1. UITableViewDelegate 和 UITableViewDataSource:用于处理表格视图的事件和数据源。

  2. UITextFieldDelegate:用于处理文本输入事件。

  3. 自定义视图或控制器的 回调:如上例中的 DownloadManagerDelegate

代理模式的优点就是为对象间的通信提供了灵活、松耦合的解决方案。