简体   繁体   English

将 @Binding 变量从协议 var 传递给 SwiftUI 中的 if

[英]Passing @Binding variable from protocol var to if in SwiftUI

I have a model like this:我有一个像这样的 model:

protocol PurchasableProduct {
    var randomId: String { get }
}

class Cart: Identifiable {
    var items: [PurchasableProduct]
    
    init(items: [PurchasableProduct]) {
        self.items = items
    }
}

class Product: Identifiable, PurchasableProduct {
    var randomId = UUID().uuidString
    var notes: String = ""
}

class DigitalGood: Identifiable, PurchasableProduct {
    var randomId = UUID().uuidString
}

where items conform to protocol PurchasableProduct .其中items符合协议PurchasableProduct

I want to build a View that shows cart like this:我想构建一个显示购物车的视图,如下所示:

struct CartView: View {
    @State var cart: Cart
    
    var body: some View {
        List {
            ForEach(cart.items.indices) { index in
                CartItemView(item: self.$cart.items[index])
            }
        }
    }
}

where CartItemView is: CartItemView在哪里:

struct CartItemView: View {
    @Binding var item: PurchasableProduct
    
    var body: some View {
        VStack {
            if self.item is Product {
                Text("Product")
            } else {
                Text("Digital Good")
            }
        }
    }
}

That's working and give me result as This (screenshot)这是有效的,并给我这个结果(截图)

But I want to extend this a but more that my items element can be passed as a binding variable lets say as:但我想扩展这个,但更多的是我的items元素可以作为绑定变量传递让我们说:

struct CartItemView: View {
    @Binding var item: PurchasableProduct
    
    var body: some View {
        VStack {
            if self.item is Product {
                VStack {
                    TextField("add notes", text: (self.$item as! Product).notes) // ❌ Cannot convert value of type 'String' to expected argument type 'Binding<String>'
                    TextField("add notes", text: (self.$item as! Binding<Product>).notes) // ⚠️ Cast from 'Binding<PurchasableProduct>' to unrelated type 'Binding<Product>' always fails
                }
            } else {
                Text("Digital Good")
            }
        }
    }
}

What I'm trying to achieve is:我想要实现的是:

  1. I have a collection of items that depends on a class should be drawn differently我有一组依赖于 class 的项目应该以不同的方式绘制
  2. Items have different editable sync that should be binded into CartView项目具有不同的可编辑同步,应绑定到CartView

Not sure if thats syntax issue or my approach issue... how to cast this on body to get the correct view based on type?不确定那是语法问题还是我的方法问题...如何将其投射到body上以根据类型获得正确的视图?

You may create a custom binding:您可以创建自定义绑定:

struct CartItemView: View {
    @Binding var item: PurchasableProduct

    var product: Binding<Product>? {
        guard item is Product else { return nil }
        return .init(
            get: {
                self.$item.wrappedValue as! Product
            }, set: {
                self.$item.wrappedValue = $0
            }
        )
    }
    var body: some View {
        VStack {
            if product != nil {
                TextField("add notes", text: product!.notes)
            } else {
                Text("Digital Good")
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM