Protocolとdelegateの関係
Protocolとdelegateの関係は密であり、Protocalでdelegateを実装するという関係です。
delegateを知る
-
delegateは使わなくてもいい - メリット:クラス側に処理の内容を任せるのではなく、自分で処理を決めることができる。
Protocolでdelegateを実装
protocol ButtonDelegate {
func delegateClicked()
}
delegateを変数として宣言
class Button {
var delegate: ButtonDelegate?
func clicked() {
if let delegate = delegate {
// 自分で実装した処理
delegate.delegateClicked()
} else {
// 通常の処理
print("クリックされました")
}
}
}
Mainクラスを実装
ここから実際にMainクラスでのdelegateの使い方を説明していきます。
冒頭で説明したようにdelegateは必ずしも必要なわけではないので、Buttonクラスでdelegate変数を宣言しましたが、使用しない方法を説明していきます。
delegateなしの場合
class Main {
let button = Button()
func clicked() {
button.clicked()
}
}
let main = Main()
main.clicked() // 「クリックされました」とprintされる
delegateありの場合
Classは継承ですが、Protocolは適合といいます。
class MainWithDelegate : ButtonDelegate { // ButtonDelegateを適合
let button = Button()
init() {
button.delegate = self // delegateをインスタンス化
}
func clicked() {
button.clicked()
}
// 自前でdelegateClicked()を実装
// Protocolを適合したので、ButtonDelegate内で宣言された関数の処理を実装しないとコンパイルエラーになる
// deletgateClicked()はButton.Click()時に呼ばれる
func delegateClicked() {
print("クリックされたよー")
}
}
let mainWithDelegate = MainWithDelegate ()
mainWithDelegate.clicked() // 「クリックされたよー」とprintされる
delegateのポイント
delegateで実装した関数は自分で呼び出すわけではない
今回の例では、勝手にclicked()関数が呼び出している。なので実装しておしまいです。呼び出す必要はありません。
別の例
Figureクラスを使いたいがgetArea()が通常の処理では、横×縦の値が返ってくるが、それを2倍にする処理にしたい
protocol FigureDelegate {
func getAreaDelegate() -> Int
}
class Figure {
var delegate : FigureDelegate?
let width : Int
let height : Int
init(width: Int, height: Int) {
self.width = width
self.height = height
}
func getArea() -> Int {
if let delegate = delegate {
return delegate.getAreaDelegate()
}
else {
return self.width * self.height
}
}
}
class Main : FigureDelegate {
let figure = Figure(width: 5, height: 7)
func setDelegate() {
figure.delegate = self
}
func printArea() {
print(figure.getArea())
}
func getAreaDelegate() -> Int {
return self.figure.width * self.figure.height * 2
}
}
let main = Main()
main.printArea()
main.setDelegate()
main.printArea()