我有一个带有 WatchViewModel 的配套 WatchOS 应用程序,它当前保存从应用程序发送的所有变量。我必须查看,每个视图都应该显示另一个变量。在一个视图 (ActivityDistributionView) 中,一切都工作得很好,但在另一个视图 (LeaderboardView) 中,该值是初始值并且不会发生更改。实际上 LeaderboardView 中没有值被更新,但在 ActivityDistributionView 中,所有值都工作正常。
我发现,如果我注释掉 ActivityDistribution 中 ViewModel 的声明,那么我的代码就可以工作。这是否意味着我只能声明该类的工作实例一次?
ContentView body:
var body: some View {
TabView{
ScoreTabView(dailyScore: viewModel.scores["score"] ?? 0, postureScore: viewModel.scores["posture"] ?? 0, movementScore: viewModel.scores["movement"] ?? 0)
NavigationStack{
List{
Section("Last message received:"){
Text("\(formatDate(date: viewModel.lastMessageTime))").font(.body)
//Text("\(viewModel.lastMessage.keys.sorted().formatted())").padding()
}
NavigationLink("Leaderboard"){
LeaderboardViews()
}
NavigationLink("Activity Distribution"){
ActivityDistributionView()
}
}
}
}
}
struct LeaderboardViews: View {
@State private var viewModel: WatchViewModel = WatchViewModel()
var body: some View {
Text("\(viewModel.leaderboardMessage)")
}
}
struct ActivityDistributionView: View {
@State private var viewModel: WatchViewModel = WatchViewModel()
@State private var vibrates = false
let activities = ["sitting", "walking", "standing", "onDesk", "driving", "lying"]
var body: some View {
NavigationStack{
ScrollView{
Text("\(viewModel.leaderboardMessage)")
}
.navigationTitle("Acitivity Distribution")
.navigationBarTitleDisplayMode(.inline)
}
}
}
@Observable
class WatchViewModel: NSObject{
var session: WCSession
var activityDistribution: [String: Any] = [:]
var scores: [String: Double] = [:]
var leaderboardMessage: LeaderboardMessage = LeaderboardMessage(method: "InitExampleLeaderboardMessage", payload: [:])
//more code
}
//Sends Data from WatchOS to AppDelegate (to later push to Flutter)
extension WatchViewModel: WCSessionDelegate {
//code that works
case .LeaderboardMessage:
self.lastMessage = message["payload"] as! [String : Any]
//message gets converted into JSON
let messageAsJSON = self.encodeJSONData(encode: message)
//message gets decoded into the proper struct
let decodedMessage = self.decodeJSONData(decode: messageAsJSON!) ?? LeaderboardMessage(method: "ExampleLeaderboardData", payload: ["Date" : [ExerciseDataWrapper(name: "Nobody", data: ExerciseData(duration: ExerciseData.Duration(displayString: "/", value: 0), exerciseScore: ExerciseData.ExerciseScore(displayString: "/", value: 0), movement: ExerciseData.Movement(displayString: "/", value: 0), posture: ExerciseData.Posture(displayString: "/", value: 0), postureAboveThresholdDuration: ExerciseData.PostureAboveThresholdDuration(displayString: "/", value: 0), score: ExerciseData.Score(displayString: "/", value: 0)))]])
//leaderboardMessage gets updated to the last send leaderboardMessage
self.leaderboardMessage = decodedMessage
//assigning works but not in the LeaderboardsView()
}
我尝试更改 NavLink 的名称和位置,或尝试将 viewModel 值从 ContentView 传递到 LeaderboardView,但没有成功。
您应该在 ContentView 上有一个实例并从那里将其传递下去。 由于某种原因,当我尝试将其从 ContentView 传递到其他视图时,Swift 决定使用 ActivityView 中声明的 ViewModel-Instance 而不是 ContentView 中声明的 ViewModel-Instance,但它们从未更新。
因此,正确的代码是将 viewModel 放在我的 ContentView 中,并将其从那里传递到我的其他视图。
struct LeaderboardViews: View {
let leaderboardMessage: LeaderboardMessage
var body: some View {
Text("\(leaderboardMessage.method)")
}
}
struct ActivityDistributionView: View {
@State private var vibrates = false
let activities = ["sitting", "walking", "standing", "onDesk", "driving", "lying"]
let activityDistribution: [String: Double]
var body: some View {
NavigationStack{
/*ForEach(viewModel.leaderboardData.keys.sorted(), id: \.self) { day in
Text("Day: \(viewModel.leaderboardData[day] ?? "No Date")")
}*/
ScrollView{
//code
}
.navigationTitle("Acitivity Distribution")
.navigationBarTitleDisplayMode(.inline)
}
}
}
struct ContentView: View {
@State private var viewModel: WatchViewModel = WatchViewModel()
@State private var vibrates = false
let activities = ["sitting", "walking", "standing", "onDesk"]
var body: some View {
TabView{
ScoreTabView(dailyScore: viewModel.scores["score"] ?? 0, postureScore: viewModel.scores["posture"] ?? 0, movementScore: viewModel.scores["movement"] ?? 0)
NavigationStack{
List{
Section("Last message received:"){
Text("\(formatDate(date: viewModel.lastMessageTime))").font(.body)
//Text("\(viewModel.lastMessage.keys.sorted().formatted())").padding()
}
NavigationLink("Leaderboard"){
LeaderboardViews(leaderboardMessage: viewModel.leaderboardMessage)
}
NavigationLink("Activity Distribution"){
ActivityDistributionView( activityDistribution: viewModel.activityDistribution as! [String: Double])
}
}
}
}
}
}