異なるコンポーネントをreturnする
2021年03月09日
if
やswitch
を使って異なるコンポーネントを返したい場合が往々にしてあります。
そのような時に以下のようなエラーに遭遇したことはないでしょうか?
// 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())
}
}