Swiftのデリゲートパターンをprotocolで実装する方法!初心者向け完全ガイド
生徒
「先生、Swiftでデリゲートパターンってよく聞くんですけど、どういう仕組みなんですか?」
先生
「デリゲートパターンは、あるオブジェクトが“自分では決めきれない処理”を他のオブジェクトに任せる仕組みです。Swiftではprotocolを使ってこの仕組みを作ることができます。」
生徒
「他のオブジェクトに任せるって、どういうイメージですか?」
先生
「例えば、テレビのリモコンを考えてみましょう。ボタンを押すのはリモコンですが、実際にテレビの電源を入れる処理はテレビ本体が担当します。この“お願いする仕組み”がデリゲートパターンです。」
1. デリゲートパターンとは?
Swiftのデリゲートパターンは、オブジェクト間で役割を分担するための設計手法です。特にiOS開発ではよく使われます。例えば、ボタンが押されたときのイベント処理や、テーブルビューのスクロールに応じた処理など、Appleのフレームワークでも多用されています。
「デリゲート」という言葉は「委任する」という意味です。つまり、あるクラスが持っている処理の一部を、別のクラスに“委ねる”ことで柔軟な設計を可能にするのです。
2. protocolでデリゲートを定義する
デリゲートパターンを作るには、まずprotocolを定義します。これは「委任する処理の設計図」です。
protocol TaskDelegate {
func taskDidFinish()
}
この場合、「タスクが終わったら呼んでね」という約束を定義しています。taskDidFinish()を実装するクラスが、処理を引き受ける“相手”になります。
3. デリゲートを持つクラスを作る
次に、デリゲートを呼び出す側のクラスを作ります。このクラスはprotocolをプロパティとして持ち、必要なタイミングで呼び出します。
class Worker {
var delegate: TaskDelegate?
func startTask() {
print("タスクを開始します...")
// タスク完了後にデリゲートへ通知
delegate?.taskDidFinish()
}
}
delegate?.taskDidFinish()のように「任せた相手がいるなら呼ぶ」という書き方をします。これにより、Workerはタスク終了後の具体的な処理を知らなくても済みます。
4. デリゲートを実装するクラスを作る
次に、実際に処理を引き受けるクラスを作ります。このクラスがprotocolを採用して、実際の処理を実装します。
class Manager: TaskDelegate {
func taskDidFinish() {
print("タスクが完了しました!マネージャーが処理を受け取りました。")
}
}
このManagerは、タスクが終わったときに呼ばれる処理を担当します。つまり、Workerが「終わったよ」と伝えると、Managerが「それなら次はこれをやる」と判断できるのです。
5. 実際に動かしてみる
最後に、デリゲートを設定して実際に動かしてみましょう。
let worker = Worker()
let manager = Manager()
worker.delegate = manager
worker.startTask()
実行すると以下のような結果が出ます。
タスクを開始します...
タスクが完了しました!マネージャーが処理を受け取りました。
この流れで、Workerはタスクの進行に集中し、Managerは終了後の処理を担当できます。役割分担が明確になり、再利用性も高まります。
6. デリゲートパターンのメリット
デリゲートパターンには以下のようなメリットがあります。
- クラス間の依存関係を減らせる
- 役割を明確に分けられる
- 処理を切り替えやすく、再利用しやすい
例えば、Managerの代わりに別のクラスをデリゲートに設定すれば、同じWorkerを使い回しながら、処理の中身を柔軟に変更できます。
7. デリゲートと日常生活の例え
初心者が理解しやすいように、デリゲートを日常生活に例えてみましょう。
例えば、あなたが宅配便を受け取るとき、自分で玄関に出られない場合、家族に「代わりに受け取って」とお願いすることがあります。このとき、あなたはWorker、家族はManager、そして「荷物を受け取る」というルールがprotocolです。家族がいれば荷物を受け取ってくれますし、いなければその処理はスキップされます。これがまさにデリゲートパターンの考え方です。