くま's Tech系Blog

基本的には技術で学んだことを書き留めようと思います。雑談もやるかもね!

Delegateとは一体??

Swiftでよく使うDelegateってよくわかんないなあ

と、最初は思っていましたが、実装していくうちにわかってきました

概念がわかりにくいかもしれませんが、必ずと言っていいほど1度は通る道なので軽くまとめようかと思います

Delegateとは一体?

最初、Swiftを始めたときに、DelegateはSwift独自のものかと思っていましたが、違いました

デザインパターンDelegateだったのです!!

ということは、デザインパターンDelegateパターンを調べてみるとスッと入りやすいかもしれません

デザインパターンなんだと理解したことで少し抵抗がなくなりました

それで、Delegateとは何でしょうか?

Delegateは一般的に「移譲」と言われ、あるクラスから他のクラスに処理を任せるというものです

とは言われてもと思った方は多いはず(自分もそう)なので、サンプル元に説明しようかと思います

Delegateサンプル

import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var TableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        TableView.delegate = self
        TableView.dataSource = self
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 2
    }
}

これはよく目の当たりにするサンプルだと思います

このViewControllerはTableViewを使うために、UITableViewDelegateとUITableViewDataSourceという2つのプロトコルに準拠しています

tableView(_ tableView, numberOfRowsInSection section)で1セクションの行数を指定しています

最初、これを見たときにどこから呼び出されているのかわからなくて悩んだ記憶があります

そこで、UITableViewのライブラリを見てみましょう

open class UITableView : UIScrollView, NSCoding, UIDataSourceTranslating {

    weak open var dataSource: UITableViewDataSource?

    weak open var delegate: UITableViewDelegate?

一部抜粋していますが、UITableViewDelegateUITableViewDataSourceの変数を持っています

Delegateの処理はUITableViewDataSourceで持っているので、そちらを見てみましょう

public protocol UITableViewDataSource : NSObjectProtocol {

    @available(iOS 2.0, *)
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int

こちらも一部抜粋ですが、1セクションの行数を返す処理がプロトコルで定義されています

そして、最初のサンプルのTableView.delegate = selfTableView.dataSource = selfでTableViewのインスタンスDelegate先をViewControllerにしています

ここまでで下記のことが分かったと思います

・どのクラスでDelegateを使うか指定する

Delegateはprotocolで定義する

Delegateを使うと指定されたクラスではprotocolで指定された関数を記述する

サンプル②

もう一つサンプルを元に説明しようかと思います

まずはDelegateの定義です

protocol ButtonDelegate {

    // ボタンを非表示にする
    func hide()
}

clickメソッドでDelegateメソッドを実行します

これは処理を任せる側です

class Button {
    var delegate: ButtonDelegate? = nil
    func click() {
        if let dg = self.delegate {
            dg.hide()
        } else {
            print("何もしないっす")
        }
    }
}

そして処理を任される側の処理を書きます

class Button2: ButtonDelegate {
    func hide() {
        print("非表示だぜ!!")
    }
}

こうすることでhide()はButton2に任せる準備ができましたね

let button = Button()
 
let button2 = Button2()
button.delegate = button1
button.click()  // 非表示だぜ!!が出力される

button.delegate = button1でbuttonのDelegateをbutton1に任せるのでclickしたときに非表示だぜ!!が出力されます

他のクラスでも使うことがほとんどなのでprotocolで定義しているということがわかるかと思います

まだ?マークの人も多いかもしれません

開発していくうちに理解していけますので、いっぱい実装しましょう

また、Delegateを使わなくても開発できてしまうので、意識して実装すると理解が早まると思います

参照

【swift】イラストで分かる!具体的なDelegateの使い方。