swift protocol and selector

18
Swi$ Protocol and Selector 2016/02/06 @TachibanaKaoru

Upload: toyship

Post on 11-Feb-2017

722 views

Category:

Technology


1 download

TRANSCRIPT

Swi$%Protocol%and%Selector2016/02/06@TachibanaKaoru

自己紹介渋谷のVOYAGE'GROUPでiOSエンジニアをしています。Twi$er:(@TachibanaKaoruBlog(:(h$p://www.toyship.org/

朝時間jpというアプリをだしてます。

try!%Swi)

• h#p://tryswi-conf.com/

• 2016/3/293/4

• VOYAGEAGROUPはtry!ASwi-のスポンサーをしています。

iOS$Developers$Conference$2016

*"h$ps://iosdc.jp*"2016/08/20*"@iosdcjp

Swi$%Protocol%Extension

Swi$%2.0から導入された機能。いままでインターフェース定義としてしか使えなかったProtocolの実装部分も共通化できるように

なりました。

デバッグ出力を共通化してみる例• こんなデバッグ出力用のプロトコルを作ったとします。protocol DebugLog {

func writeDebugMessage() -> Void

}

デバッグ出力を共通化してみる例• Swi%1.0ではこのプロトコルに適合しているクラスで実装を書く必要がありました。

class ElmViewController : UIViewController, DebugLog {

override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) writeDebugMessage() }

func writeDebugMessage() -> Void{ print("デバッグ出力の実装をここでする") }}

デバッグ出力を共通化してみる例• Swi%&2.0では、プロトコル側にデフォルトの実装をかくことができます。

protocol DebugLog {

func writeDebugMessage() -> Void

}

extension DebugLog {

func writeDebugMessage() -> Void{ print("Protocol extensionで共通化されたデバッグ出力です。")

}

}

デバッグ出力を共通化してみる例• Swi%2.0ではこのプロトコルに適合すれば実装を書く必要がなくなりました。

class ElmViewController : UIViewController, DebugLog {

override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) writeDebugMessage() }

// 書かなくていい // func writeDebugMessage() -> Void{// print("デバッグ出力の実装をここでする")// }}

デバッグ出力を共通化してみる例• では、もし、Swi%2.0で処理が共通化されているプロトコルについて、自分のクラスで実装を書いたらどうなるでしょうか。

• 自分のクラスの実装コードが実行されますclass ElmViewController : UIViewController, DebugLog {

override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) writeDebugMessage() }

func writeDebugMessage() -> Void{ print("デバッグ出力の実装をここでする") }}

Swi$%2.0%Protocol%Extension

• プロトコル側に共通実装をもたせることで、実装を共通化できるが、上書きすることでクラスごとの独自処理にすることもできる

Swi$%2.0%Protocol%Extension

• protocolを適合しているクラスによって実装を変更したりも可能

protocol DebugLog { func writeDebugMessage() -> Void}extension DebugLog { func writeDebugMessage() -> Void{ print("Protocol extensionで共通化されたデバッグ出力です。")

}}extension DebugLog where Self : UIViewController{ func writeDebugMessage() -> Void{ print("Protocol extensionで共通化されたデバッグ出力です。(ただし、selfがUIViewControllerです)") }}

プロトコルで実装したものをSelectorとしてよんでみる• 下記のように、自分で実装しているProtocolをselectorでよびだす。>実行される

class ElmViewController : UIViewController, DebugLog {

override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) performSelector("writeDebugMessage") }

func writeDebugMessage() -> Void{ print("デバッグ出力の実装をここでする") }}

プロトコルで実装したものをSelectorとしてよんでみる• 下記のように、2.0のProtocol+extensionをselectorでよびだしてみましょう

class ElmViewController : UIViewController, DebugLog {

override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) performSelector("writeDebugMessage") }

}

プロトコルで実装したものをSelectorとしてよんでみる• 下記のように、2.0のProtocol+extensionをselectorでよびだす。

• 実行時エラーとなります[Forest.ElmViewController writeDebugMessage]: unrecognized selector sent to instance

Protocol'Extensionで実装したメソッドはSelectorとして指定することができない

• Apple&Developer&Forumでもまったく同じ話題がでていました。

• Func0on&in&Swi4&2&protocol&extension&returns&unrecognized&selector&when&using&a&UIGestureRecognizer&to&call&it.

• hCps://forums.developer.apple.com/thread/16773

Selectorで指定できないとなにが困るのか。

例えば、UIBu%onのAc*onや、NSTimerやGestureのAc*onなど、UIKitの主要機能のAc*onの指定をすることができない。