Help us understand the problem. What is going on with this article?

【Swift】"Delegate"の正体を見破った

0. 注意

この記事は、Swiftを学習中の初心者(筆者自身)が試行錯誤の末、"Delegate"というものをなんとなく理解できた瞬間の余熱で書いています。

1. 概要

Swiftを学習している人なら誰でも、様々な箇所で出くわす"Delegate"という言葉。
どこかで必要になりそうとは思っていても、解説記事を理解しようと挑んでは撃沈してきた初心者は数知れず。

そんな、Swift初心者にとって悪魔的な"Delegate"を、なるべくわかりやすく説明したいと思います。

2. "Delegate"という言葉の定義

いきなり"Delegate"と言われて初心者が思い浮かぶものには、だいたい以下の二つがあるのではないでしょうか。

  1. プロパティとしてのdelegate
  2. delegateプロパティを使って構築されるコードの書き方

一つ目のものは、tableView.delegate = selfなどの記述で触れる機会が多いと思います。

問題は二つ目です。
delegateプロパティを使った処理は、一体なんのために行われているのでしょうか?
以下、"Delegate"とはこの二つ目の方である、特殊なコードの書き方のことを意味します。

3. 結局"Delegate"っていつ使うの

結論からいうと、「"Delegate"を使わないと作れない処理」なんてものは存在しません。

なぜなら"Delegate"とは、「こういう風にコードを書くとキレイだよね〜」というものだからです。(正式には、デザインパターンの一種というみたいです。)

しかし実際にSwiftを使っていると、"Delegate"を使った処理にぶち当たることは多々あります。
自分で使わない分には良いにしても、どういう処理をしているのかわかっておきたい人は、この先を読み進めてください。

4. "Delegate"は何をやっているのか、ポケモンで解説

とりあえずポケモンを使って"Delegate"を実装してみます。

目的は、タケシ・サトシなどのキャラクターごとに、自分のタイプとポケモンを出力できるようにすることです。

はじめに、使用する関数をprotocolの中で宣言しておきます。

Protocol.swift
protocol pokemonDelegate {
  //キャラの専門タイプを出力
  func myType()
  //キャラが使うポケモンを出力
  func myPokemon()
}

次に、それぞれのキャラがどんなポケモンを使うのか、具体的に記述していきます。

ポケモンを知らない方に説明すると、タケシくんは「いわ」タイプが専門で、「イシツブテ」というポケモンを使います。
サトシくんには専門のタイプはありませんが、「ピカチュウ」というポケモンを使っています。

Takeshi.swift
class Takeshi: pokemonDelegate {
  func myType() {
    print("いわ")
  }
  func myPokemon() {
    print("イシツブテ")
  }
}
Satoshi.swift
class Satoshi: pokemonDelegate {
  func myType() {
    print("特になし")
  }
  func myPokemon() {
    print("ピカチュウ")
  }
}

以上のように、一人のキャラに対して最初に宣言した関数の処理を記述すればOKです。

次に、キャラの処理のうち、使うものと使わないものを分けるコード書きます。
先ほどはprotocolで宣言した関数の中身を記述しましたが、今回はそれらの関数のうちどれを使う決めることができます。

Characters.swift
class Characters {
  //"delegate"という変数に、"Takeshi"や"Satoshi"のクラスを代入することができます。
  //これによって、キャラごとに行う処理と行わない処理を分けることができます。
  var delegate: pokemonDelegate?

  func checkCharacter() {
    if type(of: delegate) == Takeshi.self {
      //タケシの場合は、タイプとポケモンを両方とも出力
      delegate.myType()
      delegate.myPokemon()
    } else if type(of: delegate) == Satoshi.self {
      //サトシの場合は、ポケモンのみ出力
      delegate.myPokemon()
    }
  }
}

これで"Delegate"の構成は完成です。
あとは適当なViewControllerで呼び出して、実装してみましょう。

MyViewController.swift
class MyViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()

    //先ほど作成したクラスのインスタンスを作成
    let characters = Characters()
    let takeshi = Takeshi()
    //今回は変数"delegate"にtakeshiを代入
    characters.delegate = takeshi
    //処理を実行
    charachers.checkCharacter()
  }
}

コンソールに以下のように出力されるはずです。

出力結果
いわ
イシツブテ

これをサトシに置き換えると、以下のようになるはずです。

MyViewController.swift
class MyViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()

    let characters = Characters()
    let satoshi = Satohi()
    characters.delegate = satoshi
    charachers.checkCharacter()
  }
}
出力結果
ピカチュウ

5. まとめ、"Delegate"を構成するもの

以上をまとめると、"Delegate"とは

・メソッドの一覧
 →(protocolで定義)
・パターン毎のメソッドの具体的な処理
 →(protocolを継承したTakeshi, Satoshi)
・パターン毎に使用するメソッドの取捨選択
 →(Takeshiの中から実行する関数を選ぶ)

の3つから構成された、コードの記述方法です。

"Delegate"を使う強みは、同じような処理の機能が複数ある場合、画一的に機能の処理を記述でき、さらに機能ごとに実行する処理の制御ができることではないでしょうか。

6. 最後に

ここまで読んだ方ならわかると思いますが、正直Swift初心者が"Delegate"を使いこなしてコーディングするのは難しいと思います。

先ほども書きましたが、あくまで"Delegate"はコードの記述方法の一つです。
いうなればクラスの親子関係を整理したり、処理を関数にしてまとめるような、機能の実装が完了した後の可読性を上げる段階で、初めて導入を検討するものだと思います。

なのでもし今実装できない処理があり困っている方は、"Delegate"を使わないでできる方法があるはずなので頑張って探してみてください。
コーディングがひと段落してから見直すと、新しい発見があるかも知れません。

正直"Delegate"を理解したらSwiftでなんでもできるようになる思っていた筆者にとっては、なんとも言えない結論になってしまいました……。

本文中に誤り等ございましたら、コメントよろしくお願いいたします。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away