Swift / SwiftUI'de birden çok görünüm türü içeren dizi

Aug 18 2020

İnsanların tercih ettikleri arka plan görüntüsünü seçebilecekleri bir görünüm oluşturmak istiyorum, bunlar ön plan rengine sahip bir dikdörtgen veya bir görüntü içerir. Şimdiye kadar bunu oluşturarak çalıştım

Struct:

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

Onları böyle bir diziye ekliyorum

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

bu da bir dizi Arka Plan Resimleri arasında döngü yapmamı sağlıyor.

Görünüm:

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

Ancak ekleyemiyorum

 .resizable()
 .aspectRatio(contentMode: .fill)

AnyView buna izin vermediği için görüntüler için.

Bunu başarmanın daha iyi bir yolu var mı? Bunun yerine Şekiller / Görüntüler için sadece iki ayrı dizim mi olmalı? Yoksa buna daha uygun alternatif bir View yapısı var mı?

Teşekkürler!

Yanıtlar

1 vacawama Aug 18 2020 at 19:51

@ DávidPásztor'un yorumlarda bahsettiği gibi Görünümleri ViewModel'inizde saklamak kötü bir tasarımdır.

Gerçekten sadece bir renk ve bir resim adı kaydetmeniz gerekiyor. Görünüm bina kodunun gerçek görünümleri oluşturmasına izin verin.

İşte olası bir uygulama.

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

Not:enum imageName ile renk arasındaki ayrımı saklamak için bir kullanmayı düşündüm , ancak en basitinden sadece isteğe bağlı seçenekleri kullanmak ve ihtiyacım olanı saklamaktı. Görünüm oluşturma koduna maruz kalan arabirimle, uygulamayı, bilgileri depolamak istediğiniz şekilde kolayca değiştirebilirsiniz.