选择为结构的SwiftUI Picker

时间:2019-12-18 21:55:09

标签: swift swiftui picker

我正在尝试使用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("Pet", selection: $petSelection) {
ForEach(0 ..< Self.pet.count) { index in
    Text(Self.pet[index].name).tag(index)
    }

但是想知道是否可以使用struct作为选择。谢谢

4 个答案:

答案 0 :(得分:0)

您使用以下方式:

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

答案 1 :(得分:0)

// For examle bool A::doA() { bool isSuccess = true; isSuccess &= b.doB(); isSuccess &= c.doC(); this->a++; return isSuccess; } $petSelection的类型必须与结构中的Picker(selection:[...]相同。 因此,在您的情况下,您必须更改id以键入是否为$petSelection,因为集合中的项目具有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中删除参数id:

那是我想到的最好的解决方案。

答案 2 :(得分:0)

这是我的方法:

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

}

答案 3 :(得分:0)

简短答案:与您的tagPicker)中的条目Text关联的类型必须与用于存储选择。

在您的示例中:您可以选择Pet?(可能允许“空选择”),但是传递给ForEach的数组的类型为[Pet]。因此,您必须在条目中添加.tag(item as Pet?),以确保选择有效。

ForEach(Self.pets) { item in
    Text(item.name).tag(item as Pet?)
}

以下是我最初的替代答案(摆脱了可选性):

您已将选择定义为结构Optional的{​​{1}}。选取器似乎无法正确处理Optional结构作为其选择类型。

例如通过引入“虚拟/未选择的宠物”来摆脱可选项后,Pet?就会重新开始工作:

Picker

在您看来初始化选择:

extension Pet {
    static let emptySelection = Pet(name: "", age: -1)
}

希望这对您也有帮助。