3

次のようなクラスメソッドを持つ既存のクラスの拡張機能を使用しようとしています:

@objc public protocol MyProtocol {
    optional class func foo() -> Int
}

そして、私はこのプロトコルを次のような一般的な拡張機能で使用しています:

extension MyClass {

    public func bar<T: MyProtocol>() {
        ...
        let x: Int = T.self.foo!() // if I do not use "self" or "!" here, I will have a compiler error
        ...
    }

これは機能するはずですが、ビルドすると、Xcode は「コマンド /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1」と表示します。プロトコルで「オプション」を使用しない場合、拡張機能で foo() をアンラップする必要はなく、「セルフ」を削除してもすべてが正常に機能します。オプションを適切に機能させる理由と方法を誰か教えてもらえますか? 前もって感謝します。

4

1 に答える 1

2

Swift コンパイラにクラッシュの原因となっている (あまり目立たない) バグが見つかったようです。これは、単一のファイルでクラッシュするために必要なすべての複製ですswiftc

import Foundation
@objc protocol P { optional class func f() }
func f<T: P>(t: T) { T.self.f?() }

f(クラッシュするために呼び出す必要はありません)

コンパイラのクラッシュは、コードに関係なく予期される動作ではないため、おそらくレーダーを提出する必要があります。

なしでこれを行おうとすると、うまくoptionalいきます (また、 を捨てることもできますself)。私の推測では、ジェネリックの実装は現在、オプションのクラスレベル関数の可能性を考慮していません。

次のようなジェネリックなしで実行できます。

func f(p: MyProtocol) {
    (p as AnyObject).dynamicType.foo?()
}

(もっと良い方法があるかもしれませんが、私はそれを見つけることができません).

AnyObject直接呼び出そうとすると、 「プロトコル型値 'MyProtocol.Type' のメンバーへのアクセスは実装されていません」.dynamicType.foo?()と表示されるため、キャストが必要です。pジェネリック版のクラッシュがこれに関係していても不思議ではありません。

また、オプションのメソッド(特にクラスレベルのもの)を持つプロトコルが本当に必要かどうか、およびジェネリックを使用して完全に静的にやりたいことを行う方法があるかどうかを自問する価値があると思います(すでに半分やっているように) .

于 2015-01-05T18:10:52.750 に答える