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

如何在Live Activity中添加可自定义的正常工作的ProgressView?

在Live Activity中实现自定义ProgressView的正确方式

可以在Live Activity中添加自定义ProgressView,但不能用普通Timer驱动进度更新——Live Activity的运行环境受WidgetKit限制,系统不会允许后台持续运行Timer,视图更新必须通过ActivityKit的状态同步机制触发。

你的代码问题分析

  1. Timer逻辑错误:初始progress = 100.0,判断条件if progress > 100永远不成立,所以进度不会变化;
  2. Live Activity运行机制限制:即使逻辑正确,前台App的Timer.publish也无法在Live Activity的视图中生效,因为WidgetKit的视图刷新由系统调度,而非自定义Timer。

正确实现方案

通过ActivityKit的ActivityAttributes传递进度状态,系统会自动触发Live Activity视图刷新。

1. 定义Activity属性

首先创建包含进度信息的ActivityAttributes和ContentState:

import ActivityKit

struct CustomProgressAttributes: ActivityAttributes {
    // 静态属性(可选,比如任务名称)
    var taskName: String
    
    // 动态状态(用于传递实时进度)
    public struct ContentState: Codable, Hashable {
        var currentProgress: Double
        var totalProgress: Double
    }
}

2. 编写Live Activity视图

在Widget中使用ContentState的进度值渲染ProgressView:

import WidgetKit
import SwiftUI

struct CustomProgressLiveActivity: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: CustomProgressAttributes.self) { context in
            // 主视图(锁屏/通知中心显示)
            VStack(spacing: 8) {
                Text(context.attributes.taskName)
                    .font(.headline)
                ProgressView(value: context.state.currentProgress, total: context.state.totalProgress)
                    .progressViewStyle(LinearProgressViewStyle(tint: .systemBlue))
                    .padding(.horizontal)
                Text("\(Int(context.state.currentProgress))/\(Int(context.state.totalProgress))")
                    .font(.caption)
            }
            .padding()
            .background(Color.systemBackground)
        } dynamicIsland: { context in
            // Dynamic Island视图(可选,适配iPhone 14+)
            DynamicIsland {
                DynamicIslandExpandedRegion(.center) {
                    ProgressView(value: context.state.currentProgress, total: context.state.totalProgress)
                        .padding()
                }
            } compactLeading: {
                Text("\(Int(context.state.currentProgress))")
            } compactTrailing: {
                ProgressView(value: context.state.currentProgress, total: context.state.totalProgress)
                    .frame(width: 40)
            } minimal: {
                Text("\(Int(context.state.currentProgress))%")
            }
            .keylineTint(.systemBlue)
        }
    }
}

3. 在App中更新进度

通过Activity.update(using:)方法同步进度状态,系统会自动刷新Live Activity视图:

import ActivityKit

// 启动Live Activity
func startCustomProgressActivity() {
    let attributes = CustomProgressAttributes(taskName: "自定义进度任务")
    let initialState = CustomProgressAttributes.ContentState(currentProgress: 0, totalProgress: 100)
    
    do {
        let activity = try Activity.request(attributes: attributes, contentState: initialState, pushType: nil)
        
        // 模拟进度更新(替换为实际业务逻辑)
        Task {
            for progress in 0...100 {
                try? await Task.sleep(nanoseconds: 1_000_000_000) // 每秒更新一次
                await activity.update(using: CustomProgressAttributes.ContentState(
                    currentProgress: Double(progress),
                    totalProgress: 100
                ))
            }
            // 结束Activity
            await activity.end(using: CustomProgressAttributes.ContentState(
                currentProgress: 100,
                totalProgress: 100
            ), dismissalPolicy: .immediate)
        }
    } catch {
        print("启动Live Activity失败:\(error.localizedDescription)")
    }
}

关键说明

  • Live Activity的视图刷新完全依赖系统调度,只有更新ContentState才能触发视图更新;
  • 避免在Live Activity视图中使用@State+Timer的方式,这种模式仅适用于前台App;
  • 如果需要更复杂的自定义样式,可以通过progressViewStyle自定义ProgressView的外观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 04:35:28