LoginSignup
6
6

【Swift】よく分からなかったdelegateについて整理してみた(初心者が初心者のために)

Last updated at Posted at 2020-03-20

そもそもdelegateってなんだ

言葉を調べてみる

delegateを辞書で調べてみると、

1.委任する
2.代表[代理]に立てる

という意味らしい。

なるほど、言葉の意味は分かった。

Swift的観点で調べる

では、Swiftにおいて、delegateってなんだ?ともう少し調べてみると、

「delegateとは、デザインパターンのひとつです。」

なんて出てきた。

なるほど、分からないようで分からない。

分からんかったからさらに調べる

さらに調べていくと、TECHACADEMYにたどり着いた。
https://techacademy.jp/magazine/15055

ここでは、

『実際のイメージとしては「ある特定の事項について、問い合わせ先を指定する」操作と覚えておくと分かりやすいです。』

と書いてあった。

delegate = 問い合わせ先とも書いてあって、これが一番理解しやすいような気がする。(なんとなく)

まあ、とりあえず実装してみないと分からないイメージつかないので、実装に移りたい。

delegateを実装するために必要なもの

1.protocol

委任する処理をmethodとして定義する。これをデリゲートメソッドと呼ぶ。
言わば「仕様書」と言ったところ。

2.処理を委任するclass

デリゲートメソッドを使用して、処理の流れを記述する。

3.処理を委任されるclass

protocolで定義されたデリゲートメソッドを実装する。

実際に実装してみる

1.protocol

メソッドを定義する。

HorseDataProtocol.swift
protocol horseDataDelegate {
    
    func horseName() // 競走馬名
    func horseBirthYear() // 競走馬の誕生年
    func horseWinNumber() // 競走馬の勝利数
    func horseIsLeadingSire() // 競走馬の種牡馬状況
    
}

2.処理を委任するclass

今回はViewController内に実装した。

ViewController.swift
import UIKit

class ViewController: UIViewController {
    
    var delegate: horseDataDelegate? //delegateを定義
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //使用するdelegateをここで呼び出す
        delegate = DeepImpact()
        
        //delegate内のメソッドを呼び出す
        delegate?.horseName()
        delegate?.horseBirthYear()
        delegate?.horseWinNumber()
        delegate?.horseIsLeadingSire()
    }
}

3.処理を委任されるclass

protocolに記載したメソッドを使用して記載する。

DeepImpact.swift
class DeepImpact: horseDataDelegate {
    
    func horseName() {
        print("Horse Name is Deep Impact")
    }
    
    func horseBirthYear() {
        print("Horse was born in 2002")
    }
    
    func horseWinNumber() {
        print("Horse won 12")
    }
    
    func horseIsLeadingSire() {
        print("Horse is Leading Sire")
    }
    
}

これでRunすると、こんな感じで出力される。

出力
Horse Name is Deep Impact
Horse was born in 2002
Horse won 12
Horse is Leading Sire

共通なメソッドをprotocolに用意する

ここでまとめても良かったが、もう少し突っ込んでみる。

horseDataDelegateのクラスをもう一つ作成してみた。

Orfevre.swift
class Orfevre: horseDataDelegate {
    
    func horseName() {
        print("Horse Name is Orfevre")
    }
    
    func horseBirthYear() {
        print("Horse was born in 2008")
    }
    
    func horseWinNumber() {
        print("Horse won 12")
    }
    
}

ViewControllerのdelegateもこれに伴って変更してみる。

ViewController.swift
import UIKit

class ViewController: UIViewController {
    
    var delegate: horseDataDelegate? //delegateを定義
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //delegate先を変更
        delegate = Orfevre()
        
        delegate?.horseName()
        delegate?.horseBirthYear()
        delegate?.horseWinNumber()
        delegate?.horseIsLeadingSire()
    }
}

これでRunすると、Orfevreクラスでエラーが出る。

出力
Type 'Orfevre' does not conform to protocol 'horseDataDelegate'

horseIsLeadingSireメソッドないよ!って言われてる。

基本的にprotocolに記載されているものは全部書かないといけない

が、共通でもいいメソッドがある時は、わざわざ全部のメソッドを書く必要もない.

そこで、protocolを少しだけ修正する。

HorseDataProtocol.swift
protocol horseDataDelegate {
    
    func horseName() // 競走馬名
    func horseBirthYear() // 競走馬の誕生年
    func horseWinNumber() // 競走馬の勝利数
    func horseIsLeadingSire() // 競走馬の種牡馬状況
    
}

extension horseDataDelegate {

    // このメソッドはデフォルトで実装しておく
    func horseIsLeadingSire() {
        print("Horse is not Leading Sire")
    }
}

共通で使用するメソッドは、このように、extensionで用意しておけばいい。

Orfevre.swift内のhorseIsLeadingSire()は、これをオーバーライドしているという形になる。

これでRunが通る。出力はこんな感じ。

出力
Horse Name is Orfevre
Horse was born in 2008
Horse won 12
Horse is not Leading Sire

本当は、もう少し書きたいことがあったけど、長くなりそうなので今回はここまでで。

最後に

今回作成したものはGithubに載せています。
https://github.com/taichi6930/SwiftDelegateSample

初めてQiitaに投稿してみました。
やはり文章を書くのは難しいですね。

とはいえ、自分の頭の中で整理しながら書くことができました。
これからも続けていきたいと思います。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6