169
155

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[swift]4ステップで実装できるdelegate

Last updated at Posted at 2014-11-15

こんにちは!

前回

[Swift]状態を共有して変化を伝播させるサンプル~didSetなど~
(http://qiita.com/iKichiemon/items/c38fdc4b1a3f73f1f38e)

で、delegate関連の記事を書きましたが、

今回はもっと導入部分を書きます。

具体的には

「ユーザーがメールを送信する」

状況を想定して、4ステップで実装します。

  1. 説明
  2. 実装

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()
        }
    }
}
169
155
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
169
155

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?