2016-03-26 8 views
1

Objective-Cオプションのプロトコルメソッドのデフォルトの実装を提供するにはどうすればよいですか?Objective-Cオプションのプロトコルメソッドのデフォルト実装

Ex。

extension AVSpeechSynthesizerDelegate { 
    func speechSynthesizer(synthesizer: AVSpeechSynthesizer, didFinishSpeechUtterance utterance: AVSpeechUtterance) { 
    print(">>> did finish") 
    } 
} 

期待:どのような発話が終了したときに上記の機能を実行する必要がありますAVSpeechSynthesizerDelegateに準拠したクラス。

答えて

2

あなたが実装したのとまったく同じです。違いは、メソッドが実際に呼び出される方法になります。

さんはこの非常に簡単な例見てみましょう:

let o: FooProtocol = Omitted() 
let oN = o.bar?() 

let i: FooProtocol = Implemented() 
let iN = i.bar?() 

oNiN:他のコードを追加していないことで

@objc protocol FooProtocol { 
    optional func bar() -> Int 
} 

class Omitted: NSObject, FooProtocol {} 
class Implemented: NSObject, FooProtocol { 
    func bar() -> Int { 
     print("did custom bar") 
     return 1 
    } 
} 

を、私のようなこのコードを使用する必要があることを期待したいですどちらも最終的にタイプInt?,oNであり、nil,iNはであり、我々はte xt "did custom bar" print。

重要なことに、オプションのチェーンメソッドではない:bar?()、そのかっこ内のメソッド名の間に疑問符があります。これは、Swiftからオプションのプロトコルメソッドを呼び出す必要があります。

今度は、私たちのプロトコルの拡張を追加してみましょう。

extension FooProtocol { 
    func bar() -> Int { 
     print("did bar") 
     return 0 
    } 
} 

我々は、必要に応じてメソッド呼び出しをチェーン私たちの元のコードに固執する場合は、動作中に変更はありません。

enter image description here

は、

しかし、は、プロトコル拡張を使用して、オプションでアンラップする必要はありません。私たちは、アウトアンラップオプションを取ることができ、および拡張が呼び出されます。

enter image description here

ここでの不運な問題はそれがあり、これは必ずしも、特に有用ではないということですか?今度は、毎回拡張機能で実装されているメソッドを呼び出すだけです。

の場合は、の場合は、プロトコルを使用してメソッドを呼び出しているクラスを制御しています。あなたは、クラスセレクタに応答するか否かをチェックすることができます

let i: FooProtocol = Implemented() 

if i.respondsToSelector("bar") { 
    i.bar?() 
} 
else { 
    i.bar() 
} 

enter image description here

これはまた、あなたのプロトコルの宣言を変更しなければならないことを意味:

@objc protocol FooProtocol: NSObjectProtocol 

NSObjectProtocolを追加私たちはrespondsToSelectorを呼び出すことができます私たちの議定書はまったく変更されません。@objcというマークの付いたプロトコルを実装するには、すでにNSObjectから継承していなければなりません。

言うまでもなく、Objective-CコードはSwift型でこのロジックを実行することができず、実際にはこれらのプロトコル拡張で実装されたメソッドを実際に呼び出すことはできません。あなたがAppleのフレームワークから拡張メソッドを呼び出すために何かを得ようとしているなら、あなたは運が悪いと思われます。それは、たとえあなたがSwiftでどちらか一方を呼び出そうとしているとしても、それがプロトコルメソッドマークであれば、それは非常に素晴らしい解決策ではありません。

+0

詳細な説明をありがとうございます!したがって、Appleのフレームワークのように 'プロトコル 'を制御できなければ、デフォルト実装を提供できないようです。 – chrisamanse

+2

できます。拡張機能について知らないコードで実際に呼び出される '@ objc'プロトコルの***オプションの***メソッドのデフォルト実装を提供することはできません。エクステンションは知っておかなければなりません* Swiftが(私が知る限り)両方を呼び出す正しいコードを書くことができ、Swiftが拡張機能について知らなかった場合、両方を呼び出す正しいコードがコンパイルされないためです。 – nhgrif

+0

はい。私は*オプション*メソッドを意味しました。ありがとう! – chrisamanse

関連する問題