[英]SwiftUI Picker with selection as struct
Iam trying to use Picker as selection of struct.我正在尝试使用 Picker 作为结构的选择。 Let say I have a struct "Pet" like below假设我有一个像下面这样的结构“宠物”
struct Pet: Identifiable, Codable, Hashable {
let id = UUID()
let name: String
let age: Int
}
I am getting all Pet's from some class, where Pets are defined as @Published var pets = Pet我从某个班级获得所有宠物,其中宠物被定义为@Published var pets = Pet
static let pets = Class().pets
I would like to be able to write a selection from picker to below variable:我希望能够将选择器中的选择写入以下变量:
@State private var petSelection: Pet?
Picker is:选择器是:
Picker("Pet", selection: $petSelection){
ForEach(Self.pets) { item in
Text(item.name)
}
}
Picker shows properly all avaliavble pets but when I chose one petSelection has been not changed (nil). Picker 正确显示了所有可用的宠物,但是当我选择了一个宠物时,Selection 没有改变(零)。 How should I mange it?我应该如何管理它?
Thanks!谢谢!
Edit:编辑:
Of course I know that I can use tag like below:当然,我知道我可以使用如下标签:
Picker("Pet", selection: $petSelection) {
ForEach(0 ..< Self.pet.count) { index in
Text(Self.pet[index].name).tag(index)
}
But wonder is it possible to use struct as selection.但是想知道是否可以使用 struct 作为选择。 Thanks谢谢
Short answer: The type associated with the tag
of the entries in your Picker
(the Text
s) must be identical to the type used for storing the selection.简短回答:与Picker
条目tag
关联的类型( Text
s)必须与用于存储选择的类型相同。
In your example: You have an optional selection (probably to allow "empty selection") of Pet?
在您的示例中:您有一个可选的选择(可能允许“空选择”) Pet?
, but the array passed to ForEach
is of type [Pet]
. ,但传递给ForEach
的数组是[Pet]
类型。 You have to add therefore a .tag(item as Pet?)
to your entries to ensure the selection works.因此,您必须在.tag(item as Pet?)
添加一个.tag(item as Pet?)
以确保选择有效。
ForEach(Self.pets) { item in
Text(item.name).tag(item as Pet?)
}
Here follows my initial, alternate answer (getting rid of the optionality):以下是我最初的替代答案(摆脱可选性):
You have defined your selection as an Optional
of your struct: Pet?
您已将选择定义为结构的Optional
: Pet?
. . It seems that the Picker cannot handle Optional structs properly as its selection type. Picker 似乎无法正确处理 Optional 结构作为其选择类型。
As soon as you get rid of the optional for example by introducing a "dummy/none-selected Pet", Picker
starts working again:一旦您通过引入“虚拟/未选择的宠物”来摆脱可选的, Picker
再次开始工作:
extension Pet {
static let emptySelection = Pet(name: "", age: -1)
}
in your view initialise the selection:在您的视图中初始化选择:
@State private var petSelection: Pet = .emptySelection
I hope this helps you too.我希望这也能帮助你。
You use the following way:您使用以下方式:
@Published var pets: [Pet?] = [ nil, Pet(name: "123", age: 23), Pet(name: "123dd", age: 243),]
VStack{
Text(petSelection?.name ?? "name")
Picker("Pet", selection: $petSelection){
ForEach(Self.pets, id: \.self) { item in
Text(item?.name ?? "name").tag(item)
}}}
the type of $petSelection
in Picker(selection:[...]
has to be the same type of id
within your struct. So in your case you would have to change $petSelection
to type if UUID
since your items within the collection have UUID as identifier. Picker(selection:[...]
的$petSelection
类型必须与结构中的id
类型相同。因此,在您的情况下,您必须将$petSelection
更改$petSelection
类型 if UUID
因为您的集合中的项目具有 UUID作为标识符。
Anyway since this is not what you're after, but your intention is to receive the Pet
as a whole when selected.无论如何,因为这不是您所追求的,但您的目的是在选择时将Pet
作为一个整体接收。 For that you will need a wrapper containing Pet
as the id
.为此,您将需要一个包含Pet
作为id
的包装器。 Since Pet
is already Identifiable
, there're only a few adjustments to do:由于Pet
已经是Identifiable
,所以只需要做一些调整:
Create a wrapper having Pet
as an id
创建一个以Pet
作为id
的包装器
struct PetPickerItem {
let pet: Pet?
}
Now wrap all collection items within the picker item现在将所有收集项包裹在选择器项中
Picker("Pet", selection: $petSelection) {
ForEach(Self.pets.map(PetPickerItem.init), id: \.pet) {
Text("\($0.pet?.name ?? "None")")
}
}
You can now do minor adjustments like making PetPickerItem
identifiable to remove the parameter id:
from ForEach
.您现在可以做一些小的调整,比如使PetPickerItem
识别以从ForEach
删除参数id:
PetPickerItem
That's the best solution I came up with.这是我想出的最好的解决方案。
This is how I do it:这就是我的做法:
struct Language: Identifiable, Hashable {
var title: String
var id: String
}
struct PickerView: View {
var languages: [Language] = [Language(title: "English", id: "en-US"), Language(title: "German", id: "de-DE"), Language(title: "Korean", id: "ko-KR")]
@State private var selectedLanguage = Language(title: "German", id: "de-DE")
var body: some View {
Picker(selection: $selectedLanguage, label: Text("Front Description")) {
ForEach(self.languages, id: \.self) {language in
Text(language.title)
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.