微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Swift / SwiftUI中包含多个视图类型的数组

如何解决Swift / SwiftUI中包含多个视图类型的数组

我想创建一个视图,使人们可以选择自己喜欢的背景图像,其中包括带有前景色的矩形或图像。到目前为止,我已经通过创建此代码使它起作用

结构:

    Player    Birthdate  2010 2011
    John Doe  14-3-1999  12   
    John Doe                  2
    Jane Doe  15-6-1995  3    
    Jane Doe                  1
    Alice                     3

我正在将它们添加到这样的数组中

viewmodel:

struct BackgroundImage : Identifiable{
var background : AnyView
let id = UUID()
}

这使我可以像这样遍历BackgroundImages数组

查看:

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"))))
    }

但是我无法添加

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))
        }
    }
}

对于图像,因为AnyView不允许这样做。

是否有更好的方法来实现这一目标?我应该只为Shapes / Images提供两个单独的数组吗?还是有一个更适合此的View结构?

谢谢!

解决方法

正如@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之间的区别,但是仅使用可选选项并存储我需要的选项是最简单的。使用暴露于视图构建代码的界面,您可以轻松地将实现更改为您想要存储的信息。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。