【Swift】Genericsにenum型を指定する

Genericsにenum型を指定する方法がわからず試行錯誤してみた。

enum型で定義した単位を選択するビューを汎用化するためにGenericsを使用してみたが、enum型のみに限定するための制約がよくわからず苦労した。

まず試したこととしては、とりあえず制約にenumを指定してみた。

struct GenericView<T:enum>: View    // エラー
// or
struct GenericView<T>: View where T: enum    // エラー

で、案の定エラーとなった。enumは型ではないのでそらそうか。

C#の場合は enum は System.Enum を継承しているような気がしたので、Swiftでも似た感じになっていないか探してみるが見つからない

struct GenericView<T:System.Enum>: View    // System.Enum的なものがみつからない
// or
struct GenericView<T>: View where T: System.Enum    // System.Enum的なものがみつからない

ただし、enumで継承されるいくつかのprotocolは見つかった。
なので、それを利用して制約をかけてみた。

// 単位を選択するビュー
// Unit = 単位型
// unit: Binding<Unit?> = 入出力
// units: [Unit] = 選択肢
struct UnitSelectView<Unit>: View where Unit: RawRepresentable, Unit.RawValue == String, Unit: Hashable
{
    @Binding private var m_unit: Unit?
    private let m_units: [Unit]

    init(
        unit: Binding<Unit?>,
        units: [Unit]
    )
    {
        self._m_unit = unit
        self.m_units = units
    }
    
    var body: some View
    {
        VStack
        {
            Form
            {
                Picker( "単位", selection: self.$m_unit )
                {
                    ForEach( self.m_units, id: \.self )
                    { ( unit: Unit ) in
                        Text( "\(unit.rawValue)" )
                            .tag( unit as Unit? )
                    }
                }
            }
        }
    }
}

Genericsの中で使用するメンバーに応じて、protocolを探して追加しなければならないのが、ちょっと面倒。
とりあえず目的は達成できたものの、他にいい方法はないものか?

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です