Swift 中的委托 (Delegate) 是什么?
在本文中,您将了解委托 (Delegate) 是什么以及它是如何工作的。
什么是委托 (Delegation)?
顾名思义,委托将控制权赋予其他对象。要实现委托,必须将委托对象分配给其他对象。
在 iOS 应用中,UIApplicaitonDelegate 就是一个例子。UIApplicationDelegate 允许您修改 iOS 行为,例如接收推送通知、打开 URL 和启动应用。
委托模式确保提供需要委托的功能。
委托模式使对象能够与其所有者进行通信,而无需与代码耦合。如果对象无需了解其所有者的具体类型,代码的重用和维护就会更加容易。
Swift 中的协议是什么?
协议充当一种工具,将属性和方法组合成一个实体,以便其他对象可以遵循该协议来委托任务。
我们可以实现 Swift 中类、结构体或枚举所提供的协议的属性和函数。如果这些类型中的任何一个满足协议的要求,则称该协议遵循该协议。
创建协议的语法
语法
protocol <protocol_name> {
// 在此处定义所需的方法
}
如上所示,我们为协议指定了一个协议名称,该名称在 Swift 中使用 protocol 关键字指定。通过根据协议的要求定义方法,您可以定义协议的用途。
创建委托对象
让我们尝试理解如何在 ImageDownloader 类中使用委托。我保留了一个对委托对象(ImageDownloader 类型)的可选引用,以便 ImageDownloader 类实例无需委托即可运行。如果委托成员变量为 nil,ImageDownloader 仍会下载文件并调用其自身的 didDownloadImage() 方法。
import UIKit class ImageDownloader { var urlString: String var downloadedImage: UIImage? var delegate: ImageDownloaderDelegate? init(_ urlString: String) { self.urlString = urlString } func downloadImage() // downloading image DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async { let imageURL = URL(string: self.urlString) let imageData = NSData(contentsOf: imageURL!) self.downloadedImage = UIImage(data: imageData! as Data) // update UI action on main thread DispatchQueue.main.async { self.didDownloadImage() } } } func didDownloadImage() { delegate?.didFinishDownloading(self) } }
创建协议
使用 ImageDownloader 类,我们将定义一个协议,用于在任务完成或失败时通知符合该协议的对象。该协议将包含一组规则(或函数)。
类、结构体或枚举可以遵循该协议并完成这些函数的实现。
在本例中,我们将在 ProfileController 类中遵循 ImageDownloaderDelegate 协议。现在,我们需要将委托对象设置为 ProfileController 的对象。
确保 ProfileController 类中实现了所需的函数。否则,编译器将报错。
import UIKit // Protocol Creation protocol ImageDownloaderDelegate { // notify when downloading will be finished func didFinishDownloading(_ sender: ImageDownloader) // notify when downloading will be failed func didFailedDownloading(_ sender: ImageDownloader) }
遵循此委托
现在,ProfileController 类遵循 ImageDownloaderDelegate 协议。
class ProfileController: UIViewController, ImageDownloaderDelegate { private var imageDownloader: ImageDownloader? private let profileImageView = UIImageView() override func viewDidLoad() { super.viewDidLoad() view.addSubview(profileImageView) // set profileImageView frame here as per requirement downloadImage() } private func downloadImage() { let imageURL: String = "<https://image_url_here>.com" imageDownloader = ImageDownloader(imageURL) imageDownloader?.delegate = self imageDownloader?.downloadImage() } func didFinishDownloading(_ sender: ImageDownloader) { profileImageView.image = sender.downloadedImage let urlString = sender.urlString print(urlString) } func didFailedDownloading(_ sender: ImageDownloader) { profileImageView.image = nil } }
如何创建可选协议方法?
您可以在协议中包含可选方法。您必须为可选协议方法创建一个扩展。
// protocol creation protocol ImageDownloaderDelegate { // notify when downloading will be finish func didFinishDownloading(_ sender: ImageDownloader) // notify when downloading will be failed func didFailedDownloading(_ sender: ImageDownloader) } extension ImageDownloaderDelegate { func didFailedDownloading(_ sender: ImageDownloader) { } }
结论
您将工作委托给可以完成该工作的人/事物。委托可以帮助您分离关注点、解耦类并提高代码的可复用性。委托的最佳起点是视图和视图控制器之间。