swift - Swift 中的委托(delegate)示例

标签 swift design-patterns delegates protocols delegation

关闭。这个问题需要更多focused .它目前不接受答案。












想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post .

2年前关闭。




Improve this question




我一直在努力学习如何使用协议(protocol)进行委派。我什么都明白,但除了使用表 View 和可能的 ScrollView 之外,我想不出何时使用委托(delegate)。

一般什么时候使用委托(delegate)?

最佳答案

什么是委托(delegate)?

首先,你应该知道Delegation Pattern不是 iOS 世界独有的:

In software engineering, the delegation pattern is a design pattern in object-oriented programming that allows object composition to achieve the same code reuse as inheritance.



但与 delegation in the iOS world 一起工作非常普遍,我假设您可以看到许多提供委托(delegate)/数据源的类,以便为使用的实例提供属性或行为。它是 CocoaTouch 中对象如何相互通信的主要机制之一。

备择方案:

然而,委托(delegate)并不是让对象在 iOS 中相互通信的唯一方法,你可能想知道有:
  • NotificationCenter .
  • KVO (Key-Value Observing) .
  • Completion handlers/Callbacks (using closures) .
  • Target-Action .

  • 备注 :如果您有兴趣比较它们,您可能需要查看以下文章:
  • Communication Patterns.
  • When to Use Delegation, Notification, or Observation in iOS.
  • Delegates vs Observers.


  • 什么时候使用委托(delegate)?

    所以,问题是:“那么为什么我应该使用委托(delegate)而不是那些选项?”

    我会尽量简化;当您有 时,我建议使用委托(delegate)。一对一两个对象之间的关系。为了更清楚,稍微讨论一下 NotificationCenter 的目的是尝试在使用委托(delegate)时有意义:

    通知中心 代表一对多关系;简单地说,它的工作原理是:发布(通知)关于特定事件的通知并观察(得到通知)这个通知——它可以在其他任何地方观察到;从逻辑上讲,这就是一对多关系的含义。它是 Observer Pattern 的代表.

    如何申请委托(delegate)?

    为了简化起见,我将其作为步骤提及:
  • 知乎需求:每个委托(delegate)都有自己的规则,在委托(delegate)协议(protocol)中列出,委托(delegate)协议(protocol)是一组方法签名,您应该实现这些签名以符合此委托(delegate)。
  • 符合代表团:它只是通过标记让您的类(class)成为代表。例如:class ViewController: UIViewController, UITableViewDelegate {} .
  • 连接委托(delegate)对象:将您的类(class)标记为委托(delegate)是不够的,您需要确保您希望您的类(class)确认的对象为您的类(class)提供所需的工作。
  • 实现需求:最后,您的类必须实现委托(delegate)协议(protocol)中列出的所有必需方法。


  • 例如

    听起来是不是有点困惑?一个真实世界的例子呢?

    考虑以下场景:

    想象一下,您正在构建一个与播放音频相关的应用程序。一些 viewControllers 应该有一个音频播放器的 View 。在最简单的情况下,我们假设它应该有一个播放/暂停按钮和另一个按钮,比如说,以某种方式显示播放列表,无论它看起来如何。

    到目前为止一切顺利,音频播放器 View 已分离 UIView类(class)和 .xib文件;它应该作为 subview 添加到任何所需的 viewController 中。

    现在,如何为每个 viewController 的两个按钮添加功能?你可能会想:“简单的,我会在 View 类中添加一个IBAction就可以了”,乍一看,这听起来还可以,但仔细想想,你会发现它不适用如果您正在尝试处理在 Controller 层点击按钮的事件;为了清楚起见,如果每个 viewController 在点击音频播放器 View 中的按钮时实现不同的功能会怎样?例如:点击“A”viewController 中的播放列表将显示一个tableView,但点击“B”viewController 中的播放列表将显示一个选择器。

    好吧,让我们将委托(delegate)应用于这个问题:

    “#”注释代表“如何申请委托(delegate)?”的步骤。部分。

    音频播放器 View :
    // # 1: here is the protocol for creating the delegation
    protocol AudioPlayerDelegate: class {
        func playPauseDidTap()
        func playlistDidTap()
    }
    
    class AudioPlayerView: UIView {
        //MARK:- IBOutlets
        @IBOutlet weak private var btnPlayPause: UIButton!
        @IBOutlet weak private var btnPlaylist: UIButton!
    
        // MARK:- Delegate
        weak var delegate: AudioPlayerDelegate?
    
        // IBActions
        @IBAction private func playPauseTapped(_ sender: AnyObject) {
            delegate?.playPauseDidTap()
        }
    
        @IBAction private func playlistTapped(_ sender: AnyObject) {
            delegate?.playlistDidTap()
        }
    }
    

    View Controller :
    class ViewController: UIViewController {
        var audioPlayer: AudioPlayerView?
    
        // MARK:- Life Cycle
        override func viewDidLoad() {
            super.viewDidLoad()
    
            audioPlayer = AudioPlayerView()
            // # 3: the "AudioPlayerView" instance delegate will implemented by my class "ViewController"
            audioPlayer?.delegate = self
        }
    }
    
    // # 2: "ViewController" will implement "AudioPlayerDelegate":
    extension ViewController: AudioPlayerDelegate {
        // # 4: "ViewController" implements "AudioPlayerDelegate" requirments:
        func playPauseDidTap() {
            print("play/pause tapped!!")
        }
    
        func playlistDidTap() {
            // note that is should do a different behavior in each viewController...
            print("list tapped!!")
        }
    }
    

    快速提示:

    使用委托(delegate)最流行的例子之一是 Passing Data Back View Controller 之间。

    关于swift - Swift 中的委托(delegate)示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40501780/

    相关文章:

    c++ - 在 C++ 中实现回调的最佳方法是什么

    ios - 如何在 iOS 上使用 Sign In with Google 修复 `The user canceled the sign-in flow.`?

    php - 使 DDD 接口(interface)适应具体实现

    model-view-controller - 建议不使用 Controller 基类的 MVC 框架

    java - 基于其他两个对象的子类创建一个对象

    c# - 为什么输出是5?

    c# - 将 Action<T> 转换为 Func<T,Tres> 的最佳方法是什么?

    ios - 如何将一个 Sprite 移动到其他移动 Sprite 的实际位置?

    swift - 向边界线添加水平渐变

    swift - 如何在 swift 中使用 DTCoreText (DTWillFlushBlockCallBack)