web-dev-qa-db-ja.com

Swift:特定のクラスに準拠し、同時に複数のプロトコルに準拠するプロパティ

Objective-Cでは、次のように書くことができます。

@property(retain) UIView<Protocol1, Protocol2, ...> *myView;

しかし、どうすればこのコードをすばやく書くことができますか?

プロパティを多くのプロトコルに準拠させる方法はすでに知っていますが、継承を使用しても機能しません。

var myView: ??? protocol<Protocol1, Protocol2, ...>

編集:

UIViewUIImageViewなどの多くのUILabelサブタイプを使用しており、いくつかのUIViewプロパティとプロトコルで定義されたいくつかのメソッドを使用する必要があります。最悪の場合、必要なプロパティを使用してUIViewProtocolを作成できますが、Swiftで、型とプロトコルを使用してプロパティ/変数を宣言できるかどうかはわかります。準拠する。

31
Yannick Loriot

where句 を使用して、ジェネリッククラスでこれを行うことができます。

Where句を使用すると、関連付けられた型が特定のプロトコルに準拠していること、および/または特定の型パラメータと関連付けられた型が同じであることを要求できます。

これを使用するには、プロパティが 型制約 のジェネリッククラスで定義されているクラスを作成し、プロパティの 型パラメータ が目的の基本クラスとプロトコルに一致するかどうかを確認します。

特定の例では、次のようになります。

class MyViewController<T where T: UIView, T: Protocol1, T: Protocol2>: UIViewController {
    var myView: T

    // ...
}
25
Mike S

Swift 4では、ついに可能になりました。次のように、プロトコルに準拠するクラスの変数を同時に宣言できます。

class ClassA {
    var someVar: String?
}

protocol ProtocolA {}

class ClassB {
    var someOptional: (ClassA & ProtocolA)? // here is optional value
    var some: ClassA & ProtocolA // here is non-optional value; need to provide init though :)
}

これを行う方法の1つで、おそらく少し醜いものは、UIViewのラッパープロトコルを作成することです。

protocol UIViewRef {
    var instance: UIView { get }
}

これで、Protocol1Protocol2、およびUIViewRefを実装するプロトコルを作成できます。これは、UIView自体を取得するために使用されます。

protocol MyUIViewProtocol: UIViewRef, Protocol1, Protocol2 { }

そして最後のステップは、UIViewsにUIViewRefプロトコルを実装することです。これは、私が理解しているように、すでにProtocol1Protocol2を実装しています。

// SomeOfMyViews already implements Protocol1 and Protocol2
extension SomeOfMyUIViews: MyUIViewProtocol {
    var instance: UIView { return self }
}

その結果、MyUIViewProtocolがあり、その実装者はUIViewへの参照を保持し、それぞれがProtocol1Protocol2を実装します。ただし、注意点が1つあります。UIView自体を取得するには、instanceプロパティからの参照を要求する必要があります。例えば

// Lets say we're somewhere in a UIViewController
var views: [SomeOfMyUIView] = // Get list of my views
views.forEach { self.view.addSubview($0.instance) }
5
Slabko