😎
Genericを利用してSwiftUIカスタムViewを活用しましょう
上のアプリ画面に画像が4つあリます。
画像①のViewはこちらです。
Image("画像名")
.resizable()
.frame(width: 60, height: 60)
.padding()
.background(.ultraThinMaterial)
.clipShape(Circle())
Material
型の.ultraThinMaterial
を使って背景に薄い白にしました
画像②〜④のViewはこちらです
Image("画像名2")
.resizable()
.frame(width: 60, height: 60)
.padding()
.background(.blue) //実際それぞれのカスタムカラーを使いましたが、一応デフォルトカラーで説明します
.clipShape(Circle())
.background
の部分にColor
を入れました
一つのCustom Viewを統合するために
画像①〜④のViewの違う部分をあげると
-
Image()
に入れる画像名 -
.background()
に入れるやつ
特に.background()
の部分はやっかいです。
.blue
からColor
型で、.ultraThinMaterial
はMaterial
型で、違う型なので容易く同じStruct
に入れることができません。
その問題を解決するために、Genericの登場です
Generic ってなに
Genericは、型をそんなに細かく指定しないときに使う、型指定を曖昧化するテクニックです
まずはカスタムViewとしてHandView()
を作りましょう
struct HandView: View {
var name: String
var color: Color //Material ????
var body: some View {
Image(name)
.resizable()
.frame(width: 60, height: 60)
.padding()
.background(color)
.clipShape(Circle())
}
}
var color
の型指定に困りました。片一方を指定してしまうと、もう一方のViewには適用できなくなります。
そこで、Genericを入れて、color
の型を曖昧化しましょう
+ struct HandView<T>: View {
var name: String
+ var color: T
var body: some View {
Image(name)
.resizable()
.frame(width: 60, height: 60)
.padding()
.background(color)
.clipShape(Circle())
}
}
T
はTypeの意味です。
そして、実際に入れたいColor
もMaterial
も、ShapeStyle
というプロトコルに適合されましたので
+ struct HandView<T: ShapeStyle>: View {
var name: String
var color: T
var body: some View {
Image(name)
.resizable()
.frame(width: 60, height: 60)
.padding()
.background(color)
.clipShape(Circle())
}
}
T
は、「Swift中の全ての型の中に、ShapeStyle
に適合されるやつ」を代表しました
ちなみに、SwiftUIでは以下14の型を代表しました
AngularGradient
AnyShapeStyle
BackgroundStyle
Color
EllipticalGradient
ForegroundStyle
HierarchicalShapeStyle
ImagePaint
LinearGradient
Material
RadialGradient
SelectionShapeStyle
SeparatorShapeStyle
TintShapeStyle
最後に、HandView
を使って入れ替えましょう
画像①はこうなります
HandView(name: "画像名", color: .ultraThinMaterial)
画像②〜④はこうなります
HandView(name: "画像名2", color: .blue)
Discussion