Swift 中的代表示例

Examples of Delegates in Swift

我一直在努力了解协议授权的工作原理。我什么都明白,但除了使用 table 视图和可能的滚动视图之外,我想不出什么时候使用委托。

一般什么时候使用委托?

当您想将对象 A 的某些信息或状态传递给另一个对象 B 时,使用委托。通常对象 B 是创建对象 A 的对象。

我将列出一些您将使用委托的情况。

  1. 是的,你是对的。 table 视图和滚动视图使用委托,因为它们想告诉感兴趣的人(通常是您的视图控制器)"someone selected a row!" 或 "someone scrolled the scroll view!"。不仅滚动视图和 table 视图使用委托,UITextFieldUIDatePicker 以及许多其他视图也使用委托!

  2. 视图控制器也有委托。例如,UIImagePickerController。原因和上面大致一样——因为UIImagePickerController想告诉你"an image has been selected!"这样的消息。另一个例子是 UIPopoverControllerDelegate。这位代表告诉你 "the popover has been dismissed!"

  3. 使用代表的其他 类 包括 CLLocationManager。这个代表告诉你 "the user's location has been detected" 或 "failed to detect the user's location".

  4. 当您的某个视图控制器想要向其他视图控制器发送消息时,您可以在代码中使用委托。如果它是一个设置视图控制器,它可能会发送类似 "the font size setting has been changed!" 的消息,并且关心字体大小设置更改的视图控制器将知道并更改标签的字体大小或其他内容。

什么是委派?

首先你要知道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 非常普遍,我假设您可以看到许多 classes 提供 delegation/datasource 来提供为用过的实例。它是 CocoaTouch 中对象如何相互通信的主要机制之一。


备选方案:

但是,委派不是让对象在iOS中相互交谈的唯一方法,您可能想知道有:

备注:如果您有兴趣比较它们,您可能需要查看以下文章:


什么时候使用委派?

所以,问题是:"So why should I use delegation instead of those options?"

我会尽量简化;当两个对象之间存在 一对一 关系时,我建议使用委托。只是为了更清楚一点,目标 稍微讨论一下 NotificationCenter 是为了在使用委托时尝试理解:

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

的表示

如何申请授权?

为了简化起见,我将其作为步骤提及:

  1. 了解要求:每个代表都有自己的规则,列在代表protocol 这是一组方法签名,您应该为符合此委托而实施。

  2. 符合委托:就是让你的class成为委托,标记一下。例如:class ViewController: UIViewController, UITableViewDelegate {}.

  3. 连接委托对象:将您的 class 标记为委托 不够,你需要确保你想要被你的 class 确认的对象给你的 class.

  4. 实现需求:最后,你的class必须实现所有需要的方法委托协议。


例如

听起来有点混乱吗?举个真实的例子怎么样?

考虑以下场景:

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

到目前为止一切顺利,音频播放器视图有其分离的 UIView class 和 .xib 文件;它应该作为子视图添加到任何需要的 viewController.

现在,如何为每个 viewController 的两个按钮添加功能?你可能会想:"Simply, I will add an IBAction in the view class and that's it",乍一看还可以,但稍微重新思考一下,你会发现如果你试图处理点击按钮的事件,它就不适用了控制器层;明确地说,如果每个 viewController 在点击音频播放器视图中的按钮时实现不同的功能会怎样?例如:点击 "A" viewController 中的播放列表将显示一个 tableView,但点击 "B" viewController 中的播放列表将显示一个选择器。

好吧,让我们将 委派 应用于此问题:

“#”注释代表"How to Apply Delegation?"部分的步骤。

音频播放器视图:

// # 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()
    }
}

视图控制器:

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!!")
    }
}


快速提示:

最流行的使用委托的例子之一是 Passing Data Back 在视图控制器之间。

IOS 世界中的委派,主要是在 MVC(模型视图控制器)中 是 View 与 Controller 对话的一种方式,它被称为 "blind communication" 委托意味着将“领导棒”交给另一个对象(并不真正关心谁接管但通常是控制器)来控制视图本身无法控制的组件(记住它只是一个视图)或不'拥有 让它更简单....
控制器可以与视图对话,但视图不能在没有委托的情况下与控制器对话

将方法委托给 Selectionimages

创建基类并插入以下代码

创建另一个 class 然后插入代码