Xcode
Delegate
Protocol
Swift

プロトコルとデリゲートのとても簡単なサンプルについて

More than 3 years have passed since last update.

デリゲートはよくわかりませんでした。だから、それをとても簡単に説明したいと思います。

Swiftです。

※注意。僕はエンジニアではないので、間違いなどあったらごめんなさい。ご指摘頂けるととても嬉しいです。)

どうでもよい追記:

=> エンジニアのお仕事頂けるようになったので、一応駆け出しエンジニアくらいにはなれました!(^^)/


どうしてデリゲートは分かりにくいのか。

僕はこう思います。


  • 登場人物がはっきりしていない。

  • 定義がはっきりしていない。

(はっきしているかもしれないけど、僕ははっきり理解できなかった。)

ちなみに、上の2つの曖昧なモノのうち、1つは今だに曖昧です。それでも大丈夫です。デリゲートとプロトコルについては理解できます。

登場人物だけおさえれば理解はできると思います。


まずは定義について

教科書(The Swift Programing Language)を読んでみますと、次のようにあります。


Delegation is a design pattern that enables a class or structure to hand off(or delegate) some of its responsibilities to an instance of another type.


簡単に言うと、こうです。

「デリゲートは、デザインパターンです。」

ここで僕は、生まれて初めて「デザインパターン」に出逢いました。

感動的な出逢いです。よく分からないものを調べたら、よく分からないものに出逢う。これ以上の探索をする気がいっきに失せます。

すでに諦めモードですが、せっかくなので、デザインパターンの定義をしらべてみました。個人的には一番すっきりしている定義は以下です。


A design pattern is a repeatable solution to a software engineering problem. (from techopedia)


ということで、デザインパタンの定義について雰囲気だけわかりました…。

分からない部分を無視してデリゲートを簡単に言えば、

「あるクラスは、他のクラスのインスタンスに、処理を任せることができる。」というようなこと。


登場人物について

本題に入ります。登場人物が分かれば、おしまいです。

登場人物は3人。


  • 処理を依頼する人

  • 依頼される人(代理人)

  • プロトコル

以上です。

例をつくります。

依頼するクラスを「Hoge」とします。

依頼される代理人クラスを「Piyo」とします。

そして、そのために使われるプロトコルを「Mochi」としておきます。

表示にすると以下のような感じです。

例)

依頼するクラス
プロトコル
依頼されるクラス

Hoge
Mochi
Piyo

依頼する人
->
代理人

もう、分かったようなものです。


コードを書いてみます。

Xcode6のplaygroundを使ってコードを書きます。これで説明は終わりです。


playground


// プロトコルを作る。
protocol Mochi {
func sayHello() -> String
}

// 依頼人クラス
class Hoge {

// ここで、プロトコルに従うクラスのインスタンスを用意する。
var delegate: Mochi!
func say() -> String {
return delegate.sayHello()
}
}

// 代理人クラス。クラスの後ろにプロトコルを書く。
class Piyo: Mochi {
func sayHello() -> String {
return "Hello, Piyopiyo"
}
}

let hoge = Hoge()
let piyo = Piyo()
hoge.delegate = piyo // 代理人を指定。
hoge.say() // "Hello, Piyopiyo"


ポイントは、var delegate: Mochi!だと思います。(この「delegate」は任意の文字列で大丈夫です。)


改めて、なぜデリゲートが分かりづらいかと言うと。(僕が理解できなかったかと言うと。)

一般的なデリゲートの処理では、このvar delegate: SomeProtocol!が見えないところに存在しているからです。

例えば、キーボードを押し下げるというデリゲートの簡単なサンプルがあります。

http://qiita.com/mochizukikotaro/items/b35c93866fcc55e201f3


SomeViewController.swift


import UIKit

// まず、デリゲートプロトコルを宣言
class ViewController: UIViewController, UITextFieldDelegate {

// テキストフィールドをアウトレット接続して
@IBOutlet var textHoge : UITextField

override func viewDidLoad() {
super.viewDidLoad()

// selfをデリゲートにする
self.textHoge.delegate = self
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}

// selfをデリゲートにしているので、ここにデリゲートメソッドを書く
func textFieldShouldReturn(textField: UITextField!) -> Bool {
self.view.endEditing(true)
return false
}
}


登場人物は、


  • 代理人クラス:ViewController

  • 依頼人クラス:UITextField

  • プロトコル:UITextFieldDelegate

です。が、ここでUITextFieldの中身がどう書かれているかなんて普通見ません。素人は。中身はこうなっていました。


UITextField


class UITextField : UIControl, UITextInput, UIKeyInput, UITextInputTraits, NSObjectProtocol, NSCoding {
//中略
var delegate: UITextFieldDelegate! // default is nil. weak reference
//中略
}

だから、self.textHoge.delegate = selfと書けば、ちゃんと処理を委任できるんですね。

こんなことは、「べつに普通じゃん。簡単じゃん。」と言われれば、そうなのかもしれないですが、僕としては、

var delegate: UITextFieldDelegate!という記述を、自分の目で見ないと、どこに書いてあるのか把握できないと、納得感がないのです。

だから、その辺の参考書を読んでも、デリゲートとかプロトコルについて全然分かんないんです。そもそもデリゲートの説明で、プロトコルの説明なかったりしますし。

以上です。


ちなみに、上の例はデリゲート(プロトコル)を使わなくてもできます。


playground


class Hoge2 {
var delegate: Piyo2!
func speak() -> String {
return delegate.say()
}
}

class Piyo2 {
func say() -> String {
return "こんにちは!"
}
}

var hoge2 = Hoge2()
var piyo2 = Piyo2()
hoge2.delegate = piyo2
hoge2.speak()