Swift / SwiftUIの複数のビュータイプを含む配列
Aug 18 2020
前景色の長方形や画像など、好みの背景画像を選択できるビューを作成したいと思います。これまでのところ、これを作成することでこれを機能させることができます
構造:
struct BackgroundImage : Identifiable{
var background : AnyView
let id = UUID()
}
私はそれらをそのような配列に追加しています
ViewModel:
class VM : ObservableObject{
@Published var imageViews : Array<BackgroundImage> = Array<BackgroundImage>()
init(){
imageViews.append(BackgroundImage(background: AnyView(Rectangle().foregroundColor(Color.green))))
imageViews.append(BackgroundImage(background: AnyView(Rectangle().foregroundColor(Color.yellow))))
imageViews.append(BackgroundImage(background: AnyView(Image("Testimage"))))
}
これにより、BackgroundImagesの配列を次のようにループできます。
見る:
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())]) {
ForEach(VM.imageViews, id: \.self.id) { view in
ZStack{
view.background
//.resizable()
//.aspectRatio(contentMode: .fill)
.frame(width: g.size.width/2.25, height: g.size.height/8)
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
}
}
}
ただし、追加できません
.resizable()
.aspectRatio(contentMode: .fill)
AnyViewはこれを許可しないため、画像の場合。
これを達成するためのより良い方法はありますか?代わりに、Shapes / Images用に2つの別々の配列を用意する必要がありますか?または、これにより適した代替のView構造体はありますか?
ありがとう!
回答
1 vacawama Aug 18 2020 at 19:51
@DávidPásztorがコメントで述べたように、ビューをViewModelに格納するのは悪い設計です。
本当にあなたはただ色と画像名を保存する必要があります。ビュー構築コードに実際のビューを構築させます。
これが可能な実装です。
struct BackgroundItem: Identifiable {
private let uicolor: UIColor?
private let imageName: String?
let id = UUID()
var isImage: Bool { imageName != nil }
var color: UIColor { uicolor ?? .white }
var name: String { imageName ?? "" }
init(name: String? = nil, color: UIColor? = nil) {
imageName = name
uicolor = color
}
}
class VM : ObservableObject{
@Published var imageItems: [BackgroundItem] = []
init() {
imageItems = [.init(color: .green),
.init(color: .blue),
.init(name: "TestImage")]
}
}
struct ContentView: View {
@ObservedObject var vm = VM()
var body: some View {
GeometryReader { g in
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())]) {
ForEach(vm.imageItems) { item in
ZStack{
if item.isImage {
Image(item.name)
.resizable()
.aspectRatio(contentMode: .fill)
} else {
Color(item.color)
}
}
.frame(width: g.size.width/2.25, height: g.size.height/8)
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous)
}
}
}
}
}
注:enum
imageNameとcolorの区別を保存するためにを使用することを考えましたが、オプションを使用して必要なものを保存するのが最も簡単でした。ビュー構築コードに公開されているインターフェースを使用すると、情報を保存したい方法に実装を簡単に変更できます。