SwiftUI Picker 选择结构
Posted
技术标签:
【中文标题】SwiftUI Picker 选择结构【英文标题】:SwiftUI Picker with selection as struct 【发布时间】:2019-12-18 21:55:09 【问题描述】:我正在尝试使用 Picker 作为结构的选择。假设我有一个结构“宠物”,如下所示
struct Pet: Identifiable, Codable, Hashable
let id = UUID()
let name: String
let age: Int
我从某个类中获取所有 Pet,其中 Pets 被定义为 @Published var pets = Pet
static let pets = Class().pets
我希望能够将选择器的选择写入以下变量:
@State private var petSelection: Pet?
选择器是:
Picker("Pet", selection: $petSelection)
ForEach(Self.pets) item in
Text(item.name)
Picker 正确显示了所有可用的宠物,但是当我选择一个时 petSelection 没有改变(nil)。我应该如何管理它?
谢谢!
编辑:
当然我知道我可以使用如下标签:
Picker("Pet", selection: $petSelection)
ForEach(0 ..< Self.pet.count) index in
Text(Self.pet[index].name).tag(index)
但是想知道是否可以使用 struct 作为选择。谢谢
【问题讨论】:
【参考方案1】:简短回答:与Picker
(Text
s)中条目的tag
关联的类型必须与用于存储选择的类型相同。 p>
在您的示例中:您有Pet?
的可选选择(可能允许“空选择”),但传递给ForEach
的数组类型为[Pet]
。因此,您必须在您的条目中添加 .tag(item as Pet?)
以确保选择有效。
ForEach(Self.pets) item in
Text(item.name).tag(item as Pet?)
下面是我最初的替代答案(摆脱可选性):
您已将您的选择定义为结构的Optional
:Pet?
。似乎 Picker 无法正确处理 Optional 结构作为其选择类型。
一旦您通过引入“虚拟/未选择宠物”来摆脱可选的,Picker
就会再次开始工作:
extension Pet
static let emptySelection = Pet(name: "", age: -1)
在您的视图中初始化选择:
@State private var petSelection: Pet = .emptySelection
我希望这对你也有帮助。
【讨论】:
【参考方案2】:您使用以下方式:
@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)
【讨论】:
【参考方案3】:Picker(selection:[...]
中$petSelection
的类型必须与结构中id
的类型相同。
因此,在您的情况下,您必须将 $petSelection
更改为输入 if UUID
,因为集合中的项目具有 UUID 作为标识符。
无论如何,因为这不是您所追求的,但您的意图是在选择时将Pet
作为一个整体接收。为此,您需要一个包含Pet
的包装器作为id
。由于Pet
已经是Identifiable
,因此只需要做一些调整:
创建一个将Pet
作为id
的包装器
struct PetPickerItem
let pet: Pet?
现在将所有集合项包装在选择器项中
Picker("Pet", selection: $petSelection)
ForEach(Self.pets.map(PetPickerItem.init), id: \.pet)
Text("\($0.pet?.name ?? "None")")
您现在可以进行一些小的调整,例如使 PetPickerItem
可识别,以从 ForEach
中删除参数 id:
。
这是我想出的最佳解决方案。
【讨论】:
【参考方案4】:这就是我的做法:
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)
【讨论】:
以上是关于SwiftUI Picker 选择结构的主要内容,如果未能解决你的问题,请参考以下文章
如何让 SwiftUI Picker 在子视图中工作? (变灰)
在 SwiftUI 中,我如何知道 Picker 选择何时更改?为啥 didSet 不起作用?