[英]Can I use a generic type in a state variable in SwiftUI?
Is there a way to use a generic type in a state variable in Swift?有没有办法在 Swift 的 state 变量中使用泛型类型?
I have a view which presents 3 buttons.我有一个显示 3 个按钮的视图。 Each button loads an array of items of either MyGenericObject<TypeA>
, MyGenericObject<TypeB>
or MyGenericObject<TypeC>
type and the aim is to then present a list of objects from the chosen array.每个按钮加载MyGenericObject<TypeA>
、 MyGenericObject<TypeB>
或MyGenericObject<TypeC>
类型的项目数组,然后目的是显示所选数组中的对象列表。
But XCode throws an error when I write @State var objects: [MyGenericObject<T>]?
但是当我编写@State var objects: [MyGenericObject<T>]?
The error is there even when working with an individual object instead of an array, as in the following example:即使使用单个 object 而不是数组,也会出现错误,如下例所示:
struct ObjectView: View {
// I would like the following to be @State var object: MyGenericObject<T> instead...
@State var object: MyGenericObject<TypeA>?
var body: some View {
Text("\(object?.data.name)")
// because I would then like to do something like this, if possible:
if type(of: object) == MyGenericObject<TypeA> {
...show list of item of this type
} else
if type(of: object) == MyGenericObject<TypeB> {
...show list of item of this type
}
else {
...show list of item of type MyGenericObject<TypeC>
}
// or better yet, use a switch
}
How can I use a generic type in a @State variable in SwiftUI?如何在 SwiftUI 的 @State 变量中使用泛型类型? And is there a better way to achieve what I want?有没有更好的方法来实现我想要的?
I stumbled across this question and took a look at the gist.我偶然发现了这个问题,并查看了要点。 It's a little hard to tell if this is exactly what you want, but it seems like it might get you on the right path:很难判断这是否正是您想要的,但似乎它可能会让您走上正确的道路:
protocol InstrumentType {
var name : String { get set }
var int : Int { get set }
var bool : Bool { get set }
}
class Instrument<T : InstrumentType>: ObservableObject {
@Published var object: T
init(object: T){
self.object = object
}
}
class Trumpet: NSObject, ObservableObject, InstrumentType {
@Published var name: String
@Published var int: Int
@Published var bool: Bool
init(name: String = "newTrumpet", int: Int = 1, bool: Bool = true){
self.name = name
self.int = int
self.bool = bool
}
}
class Guitar: NSObject, ObservableObject, InstrumentType {
@Published var name: String
@Published var int: Int
@Published var bool: Bool
init(name: String = "newGuitar", int: Int = 2, bool: Bool = true){
self.name = name
self.int = int
self.bool = bool
}
}
class Clarinet: NSObject, ObservableObject, InstrumentType {
@Published var name: String
@Published var int: Int
@Published var bool: Bool
init(name: String = "newClarinet", int: Int = 3, bool: Bool = true){
self.name = name
self.int = int
self.bool = bool
}
}
struct ContentView : View {
var body: some View {
_ContentView(instrument: Instrument(object: Trumpet(name: "testTrumpet")))
}
}
//VIEWS
struct _ContentView<T : InstrumentType>: View {
@StateObject var instrument: Instrument<T>
var body: some View {
InstrumentView(instrument: instrument)
.environmentObject(instrument)
.frame(width: 300, height: 100)
}
}
struct InstrumentView<T : InstrumentType>: View {
@ObservedObject var instrument: Instrument<T>
var body: some View {
VStack {
if type(of: instrument) == Instrument<Trumpet>.self {
Text("Instrument is a trumpet")
Text("\(instrument.object.name)")
Text("\(instrument.object.int)")
Text("\(instrument.object.bool ? "true" : "false")")
} else
if type(of: instrument) == Instrument<Guitar>.self {
Text("Instrument is a guitar")
Text("\(instrument.object.name)")
Text("\(instrument.object.int)")
}
else {
Text("Instrument is a clarinet")
}
Button("Update int") {
instrument.object.int += 1
}
}
}
}
Added a protocol InstrumentType
that defines the available properties on each instrument -- that allowed me to get rid of the Metadata
, since it was all stored on each instrument anyway添加了一个协议InstrumentType
,它定义了每个仪器上的可用属性——这使我能够摆脱Metadata
,因为它都存储在每个仪器上
Constrained each generic to InstrumentType
将每个泛型约束到InstrumentType
I was a little confused by the @StateObject
for each type of instrument -- I assumed that maybe what I did was what you were looking for (one generic @StateObject, but perhaps this is where the answer differs from the intent)我对每种乐器的@StateObject
感到有些困惑——我认为我所做的可能就是您要寻找的东西(一个通用的@StateObject,但也许这就是答案与意图不同的地方)
I was able to use environmentObject
and object.name
in the way you were hoping我能够以您希望的方式使用environmentObject
和object.name
Added a Button to show that the @Published properties propagate correctly.添加了一个 Button 以显示 @Published 属性正确传播。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.