ソフトウェア設計

SwiftのDelegateとObserver、いつ何を使うべきか徹底比較

iOS開発では、Delegateパターンに何度も出会います。

読了 5 分
SwiftのDelegateとObserver、いつ何を使うべきか徹底比較のカバー画像

iOS開発では、Delegateパターンに何度も出会います。

UITableViewやUITextFieldを扱うたびにdelegateを付けながら、「なぜDelegateなんだろう?クロージャや通知ではだめなの?」と考えたことはありませんか。

特にObserverパターンまで学ぶと、かえって混乱しがちです。どちらも「何か起きたら知らせる」構造ですが、何が違うのでしょうか。

まず結論からお話しします。

Delegateは、1つのオブジェクトがただ1人に「これはあなたに任せます」と委譲する1:1の通信です。

Observerは、1つのイベントを複数人が同時に購読する1:Nのブロードキャストです。

この1行を押さえるだけで、半分は理解できます。今日はコードとともに違いを整理します。


Delegateパターンとは?

Delegateは日本語で「委譲」です。

自分で処理するのが難しい仕事を、信頼できる別のオブジェクト1つに「代わりに決めて」と任せます。

実生活にたとえると、こうです。

レストランを予約したいものの自分で電話するのが面倒なので、秘書に「代わりに予約して」と頼みます。

この秘書がDelegateです。頼む側も1人、頼まれる側も1人。まさに1:1です。

Swiftでは、これをプロトコルで定義します。

// 委譲する仕事をプロトコルで定義
protocol OrderDelegate: AnyObject {
    func didFinishOrder(_ menu: String)
}

class Restaurant {
    weak var delegate: OrderDelegate?  // 1人だけ指定
    func order(_ menu: String) {
        delegate?.didFinishOrder(menu)  // その1人だけに通知
    }
}

ここで注目したいのは、delegateが配列ではなく、単一のプロパティだという点です。

1人に任せるので、当然1つだけ保持します。これがDelegateが1:1である理由です。

さらにweakが付いています。強参照し合うとretain cycleでメモリーリークが起きるため、Delegateは慣例的にweakで保持します。


Observerパターンとの違いは?

Observerは「観察者」です。

何かイベントが起きると、それを見ていた複数のオブザーバーに一斉に通知が届きます。

先ほどの秘書のたとえを続けましょう。

今度はレストランのオープン情報を近所に放送します。「今日の夕方にオープンします!」

聞く人は10人かもしれませんし、100人かもしれません。誰が聞くかは気にせず、ただ配信します。

これが1:Nの放送、Observerパターンです。

iOSではNotificationCenterが代表例です。

// イベント発生 → 購読者全員にブロードキャスト
NotificationCenter.default.post(name: .storeOpen, object: nil)

// 関心のあるオブジェクトが各自で購読
NotificationCenter.default.addObserver(
    self, selector: #selector(handleOpen),
    name: .storeOpen, object: nil)

送信側は誰が受け取るか知りません。名前を付けて投げるだけです。

受信側も複数のオブジェクトがそれぞれ購読します。

互いを知らなくてよいので結合度は低くなりますが、今誰が通知を受けているのか追跡しにくいという欠点があります。

実際にコードを書いてみて、ようやく腑に落ちました
実際にコードを書いてみて、ようやく腑に落ちました

DelegateとObserverを一目で比較

言葉だけでは混乱するので、表にまとめました。

1:1の委譲と1:Nの放送は、図で見ると明快です
1:1の委譲と1:Nの放送は、図で見ると明快です
区分 Delegate Observer
通信方式 1:1(1人に委譲) 1:N(複数人に放送)
相手を知っているか 互いを明確に知っている 互いを知らなくてもよい
代表例 UITableViewDelegate NotificationCenter
応答(戻り値) 受け取りやすい 受け取りにくい
結合度 比較的高い 低い
追跡・デバッグ 容易 やや難しい

重要なのは「応答を返してもらう必要があるか」です。

Delegateなら「このセルの高さはいくつにする?」と聞くと、相手が値を返します。会話が往復する構造です。

Observerは投げて終わりです。誰がどう反応するか、送信側は関知しません。


結局、いつ何を使うべき?

実際のプロジェクトで使って決めた基準は次のとおりです。

Delegateを使うとき

  1. 1つのオブジェクトとのみ通信するとき
  2. 相手から値を返してもらう必要があるとき(例:セル数、高さ)
  3. 画面遷移のように順序と流れが明確なとき

Observerを使うとき

  1. 1つのイベントに複数の画面が同時に反応するとき
  2. ログイン状態の変更やダークモード切り替えなど、アプリ全体のイベントのとき
  3. 送信側と受信側が互いを知らなくてよいとき

たとえばログイン成功時にホーム画面、マイページ、上部バナーが同時に変わるなら、Delegateでは対応しきれません。

1人にしか委譲できないため、3か所すべてにつなぐとコードが煩雑になるからです。

そんなときはObserverで「ログインしたよ!」と一度だけ放送するほうが、ずっとすっきりします。

反対に「入力欄の確認ボタンを押した」のような1:1の状況なら、Delegateかクロージャが適切です。

ホワイトボードに矢印で描くと、ずっと分かりやすくなります
ホワイトボードに矢印で描くと、ずっと分かりやすくなります

まとめ

似て見えても、「何人に知らせるのか」を考えれば選びやすくなります。

1人ならDelegate、複数人ならObserver。この基準だけ覚えれば十分です。

次にコードを書くとき、今日学んだことを試してみてください。頭で知っていたことが手になじむ瞬間、パターンが一気に分かりやすくなります。応援しています!

あわせて読みたい