こんにちは!
前回
[Swift]状態を共有して変化を伝播させるサンプル~didSetなど~
(http://qiita.com/iKichiemon/items/c38fdc4b1a3f73f1f38e)
で、delegate関連の記事を書きましたが、
今回はもっと導入部分を書きます。
具体的には
「ユーザーがメールを送信する」
状況を想定して、4ステップで実装します。
- 説明
- 実装
1. 説明
delegateとは、なにかの機能を指し示しているのではなく
delegateという書き方を使いましょう、というデザインパターンです。
ネットで検索するとしばしば目にするのが
「delegateは処理を 移譲 するもの」という説明。
###もっと簡単に
ですが、これでは全然分からないので、
もっと簡単にdelegateを説明してみると、
クラス自身には機能をもたせず、
「誰かこれやって!」
とお願いする書き方がdelegateです。
メール送信の例で言えば、
ユーザーがメールサーバーに送信をお願いし、その結果を表示したい時とか、
非同期で送信し、その完了イベントを通知したいときなどに利用できます。
メールサーバーに対して「このメールを送ったら教えてね!」とお願いする
イメージになります。
###必要な実装は
- プロトコル
- ユーザークラス
- メールサーバークラス
実装するもの | --------- | 名前 |
---|---|---|
メールを送信完了したら教える先 | --> | MailServerDelegate |
完了イベントを受け取りたいユーザー | --> | User |
メールを送信して完了通知するメールサーバー | --> | MailServer |
2. 実装
まず、枠を作りましょう。
STEP1. 登場するクラス・プロトコル
ユーザー。
class User {
}
メールサーバー。
class MailServer {
}
これはメール送信に関連するイベント。
protocol MailServerDelegate {
}
STEP2. delegateの仕組みを作る
それぞれの枠ができたので、
どこになにを持たせるのか、という連携部分を書いてみましょう。
ユーザーは、メール送信の完了イベントを受け取りたいので、
Delegateを実装させます。
こうすることで、
私がイベントをうけとります。
と指示できるようになります。
class User: MailServerDelegate {
/*
* ボタンが押された時の処理
*/
func sendButtonPushed() {
}
}
メールサーバーは、メール送信処理と、イベントの通知先を持ちます。
class MailServer {
// イベントを通知する先
weak var delegate: MailServerDelegate?
/*
* メールを送信する処理
*/
func sendMail(message: String) {
}
}
こちらはメール送信のイベント通知先。
どんなイベントをしてほしいかを書く。
protocol MailServerDelegate {
/*
* 送信した時のイベント
* 「メール送信成功しました!」
* 「メール送信失敗しました...」
*/
func onSuccessSendMail() -> Vold
func onFailureSendMail() -> Vold
}
STEP3. 機能実装
ゆるーい連携部分ができたので、
どういう処理をさせていくかを簡単に書きましょう
メールサーバーは、
メール送信の具体的な中身を実装する。
メール送信が呼ばれるのは、
[送信]ボタンが押されて、ユーザーがメール送信をお願いした時。
class MailServer {
// イベントを通知する先
weak var delegate: MailServerDelegate?
/*
* メールを送信する処理
* 「あ、このメッセージを送るんですね、わかりました。メール送信します。
* 完了したらdelegateに知らせますね。」
*/
func sendMail(message: String) -> Void{
// 非同期メール送信処理を書く
if 成功 {
self.delegate?.onSuccessSendMail()
} else {
self.delegate?.onFailureSendMail()
}
}
}
STEP4. 仕上げ
最後の仕上げです。
Userにdelegateを継承させて実装します!
delegateを継承させること → イベントを受け取る準備。
mailServer.delegate = self → 「イベントは私が処理します」と伝える宣言
ユーザーは、[送信]ボタンが押されたら、メールサーバーに送信依頼をします。
その結果は、非同期などであればいつ帰ってくるかわからないので、
実装したMailServerDelegateの処理が呼ばれるまで待ちます。
class User: MailServerDelegate {
let mailServer: MailServer
init(){
self.mailServer = MailServer()
self.mailServer.delegate = self // 送信結果はselfに教えてね。
}
/*
* ボタンが押された時の処理
*/
func sendButtonPushed(message: String){
// メールを送信する。送信の結果は、delegate経由で受け取る。
self.mailServer.sendMail(message)
}
// 送信結果。mailServerからコールされる
func onSuccessSendMail() -> Vold {
print("success!")
}
func onFailureSendMail() -> Vold {
print("failure..")
}
}
書いたものまとめ
いかがでしたでしょうか。
なかなかイメージしづらいdelegateですが、
少しでもお力になれれば幸いです。
class User: MailServerDelegate {
let mailServer: MailServer
init(){
self.mailServer = MailServer()
self.mailServer.delegate = self
}
/*
* ボタンが押された時の処理
*/
func sendButtonPushed(message: String){
// メールを送信する。送信の結果は、delegate経由で受け取る。
self.mailServer.sendMail(message)
}
// 送信結果。mailServerからコールされる
func onSuccessSendMail() -> Vold {
print("success!")
}
func onFailureSendMail() -> Vold {
print("failure..")
}
}
protocol MailServerDelegate {
/*
* 送信した時のイベント
* 「メール送信成功しました!」
* 「メール送信失敗しました...」
*/
func onSuccessSendMail() -> Vold
func onFailureSendMail() -> Vold
}
// メールを送信して、delegateに対して結果を知らせます。
class MailServer {
// イベントを通知する先
weak var delegate: MailServerDelegate?
/*
* メールを送信する処理
* 「あ、このメッセージを送るんですね、わかりました。メール送信します。
* 完了したらdelegateに知らせますね。」
*/
func sendMail(message: String) -> Void{
// 非同期メール送信処理を書く
if 成功 {
self.delegate?.onSuccessSendMail()
} else {
self.delegate?.onFailureSendMail()
}
}
}