You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift视图无法刷新:点击按钮重建视图未生效问题求助

解决方案

问题根源

  • 用@State存储视图实例无效:SwiftUI视图是值类型,重新赋值@State中的视图实例不会触发视图树更新,SwiftUI依赖状态变量变化而非实例引用对比来刷新视图。
  • 子视图各自持有独立数据源:RingView和RingNumbersView分别创建main实例,导致数据不共享,refresh操作无法同步通知所有子视图。
  • RingView未实现更新逻辑:updateWKInterfaceObject方法为空,即使数据源变化,底层WKInterfaceActivityRing也不会更新。
  • RingNumbersView仅加载一次数据:仅在onAppear时获取数据,后续数据源变化无法触发UI更新。

1. 统一数据管理,提升状态到父视图

将数据源实例提升到ContentView,作为共享数据源传递给子视图,避免子视图各自创建独立实例:

struct ContentView: View {
    @State var WeekElevation : FlightsClimbed = FlightsClimbed()
    // 共享的数据源实例
    @StateObject private var fitness = main()

    var body: some View {
        VStack {
            Button("refresh") {
                // 触发重新查询数据,而非重建视图
                fitness.makeQuery() { summary in
                    fitness.currentSummary = summary
                }
            }

            RingView(fitness: fitness).frame(width: 45, height: 45)
            RingNumbersView(fitness: fitness)

            VStack {
                Text("\(Int(WeekElevation.getFlights())) ") + Text(Image(systemName: "figure.stairs")) + Text(" in past week")
                Text("\(WeekElevation.calculatePercentEverest())% of Mt. Everest")
            }
        }
    }
}

2. 改造数据源类,支持状态发布

确保main类为ObservableObject,并添加可发布的HKActivitySummary属性,让数据变化能通知所有关联视图:

import Foundation
import HealthKit

class main: ObservableObject {
    @Published var currentSummary: HKActivitySummary?

    func authorizeHealthkit() {
        // 保留原有的健康权限授权逻辑
    }

    func makeQuery(completion: @escaping (HKActivitySummary) -> Void) {
        // 保留原有的HKActivitySummary查询逻辑
        // 查询完成后更新可发布属性
        let fetchedSummary = HKActivitySummary() // 替换为实际查询结果
        currentSummary = fetchedSummary
        completion(fetchedSummary)
    }
}

3. 修改RingView,实现数据更新逻辑

通过@ObservedObject接收共享数据源,在updateWKInterfaceObject中更新环形图:

import Foundation
import HealthKit
import SwiftUI

struct RingView : WKInterfaceObjectRepresentable {
    @ObservedObject var fitness: main

    func makeWKInterfaceObject(context: Context) -> WKInterfaceActivityRing {
        let ringObject = WKInterfaceActivityRing()
        // 初始化时加载已有数据
        if let summary = fitness.currentSummary {
            ringObject.setActivitySummary(summary, animated: true)
        }
        return ringObject
    }

    func updateWKInterfaceObject(_ wkInterfaceObject: WKInterfaceActivityRing, context: Context) {
        // 数据变化时更新环形图
        if let summary = fitness.currentSummary {
            wkInterfaceObject.setActivitySummary(summary, animated: true)
        }
    }
}

4. 修改RingNumbersView,响应数据变化

去掉子视图独立的数据源和状态,直接使用共享数据源的currentSummary,自动响应数据更新:

struct RingNumbersView: View {
    @ObservedObject var fitness: main

    var body: some View {
        HStack {
            if let summary = fitness.currentSummary {
                let red = Int(summary.activeEnergyBurned.doubleValue(for: .largeCalorie()))
                let green = Int(summary.appleExerciseTime.doubleValue(for: .minute()))
                let blue = Int(summary.appleStandHours.doubleValue(for: .count()))

                Text("\(red)").foregroundColor(.red)
                Text("\(green)").foregroundColor(.green)
                Text("\(blue)").foregroundColor(.blue)
            } else {
                // 数据未加载时的占位显示
                Text("--").foregroundColor(.gray)
                Text("--").foregroundColor(.gray)
                Text("--").foregroundColor(.gray)
            }
        }
        .padding()
        .onAppear(){
            fitness.authorizeHealthkit()
            // 初始化时无数据则触发查询
            if fitness.currentSummary == nil {
                fitness.makeQuery() { _ in }
            }
        }
    }
}

核心逻辑说明

  • 状态提升:将数据源集中在父视图,确保所有子视图共享同一数据,避免数据不一致。
  • 可发布属性绑定:通过@Published和@ObservedObject实现数据变化自动通知UI刷新,无需手动重建视图。
  • WatchKit组件更新:必须实现WKInterfaceObjectRepresentable的updateWKInterfaceObject方法,才能让底层WatchKit组件响应数据变化。
  • Refresh触发:点击按钮仅触发数据重新查询,通过更新共享数据源的可发布属性,自动同步所有关联子视图的UI。

内容的提问来源于stack exchange,提问作者Eddie Gabriel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 01:54:21