異なるコンポーネントをreturnする

2021年03月09日

ifswitchを使って異なるコンポーネントを返したい場合が往々にしてあります。


そのような時に以下のようなエラーに遭遇したことはないでしょうか?

// error => Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirement
func getComponent(isText: Bool) -> View {
    if isText {
        return Text("Text")
    }
    return Button(action: {}, label: {Text("button")})
}





このような場合AnyViewを利用します。

func getComponent(isText: Bool) -> AnyView {
    if isText {
        return AnyView(Text("Text"))
    }
    return AnyView(Button(action: {}, label: { Text("button") }))
}

AnyViewについて

AnyViewは以下のように定義されています

public struct AnyView : View {

    /// Create an instance that type-erases `view`.
    public init<V>(_ view: V) where V : View

    /// The type of view representing the body of this view.
    ///
    /// When you create a custom view, Swift infers this type from your
    /// implementation of the required `body` property.
    public typealias Body = Never
}

initの引数で渡した値がViewに適合している必要があるため、結果としてSwiftUIで作成したコンポーネントを指定する事が出来ます。




そのため自分で定義し作成したコンポーネントを渡す事も出来ます。

enum ComponentType {
    case text
    case button
    case original
}

struct SampleComponent: View {
    var body: some View {
        VStack {
            Text("sample component")
            Button(action: {}, label: { Text("Button") })
        }
    }
}

func getComponent(type: ComponentType) -> AnyView {
    switch type {
    case .text:
        return AnyView(Text("hello"))
    case .button:
        return AnyView(Button(action: {}, label: { Text("Button") }))
    case .original:
        return AnyView(SampleComponent())
    }
}

おすすめ