如何在 swiftui 中使用 @Published 属性 包装器更改选择器内的值

How to change values inside a picker using @Published property wrapper in swiftui

您好,我在 swiftui 中遇到了选择器视图的问题

我创建了一个只有 class 这样的文件

import Foundation
import SwiftUI


class something: ObservableObject {

    
    @Published var sel = 0
}

然后我创建了 2 个视图

import SwiftUI

struct ContentView: View {
    @StateObject var hihi: something
    
    var characters = ["Makima", "Ryuk", "Itachi", "Gojou", "Goku", "Eren", "Levi", "Jiraya", "Ichigo", "Sukuna"]
    
    var body: some View {
        VStack {
            Section{
                Picker("Please choose a character", selection: $hihi.sel) {
                    ForEach(characters, id: \.self) { name in
                        Text(name)
                    }
                }
                Text(characters[hihi.sel])

            }
            now(hihi: something())
        }
    }
}


struct now: View {
    
    @StateObject var hihi: something
    
    var body: some View {
        Text("\(hihi.sel)")
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(hihi: something())
    }
}

现在面临的问题是代码编译但选择器不工作它不会更改为数组中的任何其他值我提供它返回到其原始值,前提是第 0 个索引“ Makima”,它不会 select 任何其他选项,为什么? 请帮忙

存在三个问题,主要的一个是选择不匹配。

Picker 中,您的选择基于每个字符的字符串值。这是因为 ForEach 通过 name 字符串标识每个 Text,因为您使用了 id: \.self.

但是,您的 something 模型(按照惯例,理想情况下应该以大写字母开头)有一个数字选择。因为 Picker 中的项目有 String 个 ID,而这是一个 Int,无法设置选择。

您可以将模型更改为:

class something: ObservableObject {
    @Published var sel = "Makima"
}

这还需要在body中稍作改动:

VStack {
    Section{
        Picker("Please choose a character", selection: $hihi.sel) {
            ForEach(characters, id: \.self) { name in
                Text(name)
            }
        }
        Text(hihi.sel) // Now getting string directly

    }
    now(hihi: something())
}

请注意,我们现在有两个显示所选角色的视图 - 但只有最上面的一个更新。底部的视图现在可能是多余的(now 视图),但我将向您展示如何让它正常工作。这是我们遇到第二个问题的地方:

您在将 something() 传递给 now 时创建了一个新实例(同样,应该以大写字母开头)。这意味着 ContentView 中存储的 hihi 的当前实例不会被传递。您只是在创建一个使用默认值的 something 的新实例。这完全独立于 hihi 实例。

替换:

now(hihi: something())

与:

now(hihi: hihi)

最后一个可能不太明显的问题是,您不应该在 now 中使用 @StateObject,因为它不 拥有 [=68] =] object/data。相反,传入了 object,因此您应该使用 @ObservedObject。尽管该示例现在即使没有此更改也能正常工作,但您稍后在尝试更改 now 视图中的 object 时会遇到问题。

now 中的 @StateObject 替换为 @ObservedObject


完整答案(somethingContentView中初始化只是为了测试方便):

struct ContentView: View {
    @StateObject var hihi: something = something()

    var characters = ["Makima", "Ryuk", "Itachi", "Gojou", "Goku", "Eren", "Levi", "Jiraya", "Ichigo", "Sukuna"]

    var body: some View {
        VStack {
            Section{
                Picker("Please choose a character", selection: $hihi.sel) {
                    ForEach(characters, id: \.self) { name in
                        Text(name)
                    }
                }
                Text(hihi.sel)

            }
            now(hihi: hihi)
        }
    }
}
struct now: View {
    @ObservedObject var hihi: something

    var body: some View {
        Text(hihi.sel)
    }
}
class something: ObservableObject {
    @Published var sel = "Makima"
}