デリゲートとは
初学者の場合「デリゲート=代理人」と覚えるのが第一歩としては分かりやすい。委任や委譲といった意味もあるけど、それだと日本語的にも難しく理解しにくくなるので、デリゲート=代理人と覚えよう。
何がいいのか?
デリゲートを使うことで、ある処理を自分以外の代理人に任せることができる。それによって自分本来の仕事に専念することができるため、処理が効率化したり役割が分かりやすくなったりして色々と都合が良い。
サンプルコード
ここでは例として、あるスポーツの試合(Game)を行おうとしたときに、その試合で使うグラウンドの清掃(処理)を代理人(delegate)に任せる(委任)ようなコードを考える。
//ゲームの代理人規約(代理人は以下のメソッドを持たねばならない)
protocol GameDelegate: class {
func cleanPlayground(_ game: Game) //gameのグランドを清掃するメソッド
}
//グランド清掃役の代理人として、仕事が早いSpeedCleanerDelegateさんを用意しとく
class SpeedCleanerDelegate: GameDelegate {
func cleanPlayground(_ game: Game) {
print("Now Cleaning as fast as possible.")
}
}
//グランド清掃役の代理人として、完璧な清掃をしてくれるPerfectCleanerDelegateさんを用意しとく
class PerfectCleanerDelegate: GameDelegate {
func cleanPlayground(_ game: Game) {
print("Now Cleaning Perfectly.")
}
}
class Game { //ゲームの仕様を決めとくで
weak var delegate: GameDelegate? //わいだけでは仕事が回らんので、GameDelegateプロトコルに準拠しとる代理人を雇うことにするで!
func start() {
delegate?.cleanPlayground(self) //代理人に試合開始前は清掃をさせる
self.shout(phrase: "Now Playing") //Now Playingの宣言を(Gameクラスのインスタンスである)自分でやる
delegate?.cleanPlayground(self) //代理人に試合終了後の清掃をさせる
}
func shout(phrase: String) {
print(phrase)
}
}
let someGame = Game() //とあるゲームを作る
let speedDelegate = SpeedCleanerDelegate() //代理人として、今回はSpeedCleanerDelegateさんを作る
someGame.delegate = speedDelegate //わいの代理人としてspeedDelegateさんに任命したろ!
someGame.start() //ゲーム開始や!
実際のiOSアプリ開発では
実際のiOSアプリの開発ではTableViewを使うときには必ずdelegateを使うことになる。
- 代理人(Delegate): ViewController
- 処理を委任する側: TableView
- プロトコル:UITableViewDelegate
例としてRSSリーダーのようなサーバーからAPI通信で記事を取得してTableViewで記事一覧を表示するArticleListViewControllerクラスを考えてみる。
import UIKit
class ArticleListViewController: UITableViewController, UITableViewDelegate {
@IBOutlet weak var tableview: UITableView!
var articles: [Article]
override func viewDidLoad() {
super.viewDidLoad()
tableview.delegate = self
// ビューが読み込まれた時の処理
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: ArticleCell.self, for: indexPath)
cell.title = articles[indexPath.row].title
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return articles.count
}
}
class UITableView: UIScrollView { // 実際にはここはAppleが標準でObjective-Cで定義しているのでイメージとしてこんな感じになってますという程度でみてください
weak var delegate: UITableViewDelegate?
var rowCount: Int
var sectionCount: Int
override init(frame: CGRect) {
super.init(frame: frame)
for i in rowCount {
delegate.tableView(self, cellForRowAt: i)
}
for j in sectionCount {
delegate.tableView(self, section: j)
}
}
}
// ごめん、実際のUITableViewの定義全然違うと思うし、UITableViewDelegateはDelegateの説明の実例として分かりにくくて不適切だった・・・
tableView.delegate = self を忘れがち!
上記でも書いたように、実際のiOSアプリ開発ではtableView.delegate = self
をよく書き忘れます。
あとがき
Swiftを学び始めたとき、読んでた本にも、ネット上の情報にもDelegateの説明で分かりやすいものがなかったのでこの記事を書いたのですが、ちょいちょい追記したりしたものの、UITableViewDelegateの説明とか全然分かりやすくないと思う・・・。リクエストいただければちゃんとした実例を元に書き直しますm(__)m