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

SwiftUI LiveActivities启动时抛出异常问题求助

Live Activity 无法启动的排查与解决建议

问题排查方向及修复方案

  • 系统与设备要求:Live Activity仅支持iOS 16.1及以上版本,DynamicIsland功能仅限iPhone 14 Pro系列及以上机型,必须用真机测试,模拟器大概率无法正常运行。
  • Widget配置校验:
    • 确保Widget Extension的Deployment Target与主App完全一致,且不低于iOS 16.1。
    • 检查Widget的Info.plist,需添加NSWidgetConfigurationFamily并包含activity值(默认可能只有systemSmall等,需手动补充)。
  • Info.plist设置确认:主App和Widget的NSSupportsLiveActivities必须设为布尔类型的YES,不能是字符串类型。
  • DynamicIsland视图补全:空的DynamicIsland闭包可能引发渲染异常,建议为各区域添加基础视图,示例:
    dynamicIsland: { context in
        DynamicIsland {
            DynamicIslandExpandedRegion(.center) {
                Text(context.attributes.timerName)
            }
            DynamicIslandExpandedRegion(.bottom) {
                Text(context.state.endTime, style: .timer)
            }
        } compactLeading: {
            Text("⏱️")
        } compactTrailing: {
            Text(context.state.endTime, style: .timer)
        } minimal: {
            Text("⏱️")
        }
    }
    
  • 共享类型访问权限:TimerAttributes需在主App和WidgetExtension之间共享,建议将其放入共享Framework,或在主App的Target Membership中勾选WidgetExtension,确保Widget能访问该结构体。
  • 错误类型细化排查:修改startActivity中的错误捕获逻辑,精准定位问题:
    do{
        activity = try Activity.request(attributes: attributes, contentState: state)
    } catch let error as ActivityError {
        print("Activity错误: \(error)")
        switch error {
        case .activityAlreadyExists: print("Activity已存在")
        case .notSupported: print("设备不支持Live Activity")
        case .permissionDenied: print("权限被拒绝")
        default: print("其他状态错误")
        }
    } catch {
        print("未知错误: \(error)")
    }
    
  • 主视图入口校验:确保MainView被正确添加到App入口:
    @main
    struct TutorialApp: App {
        var body: some Scene {
            WindowGroup {
                MainView()
            }
        }
    }
    

你提供的代码参考

TimerAttributes.swift

import ActivityKit
import SwiftUI

struct TimerAttributes: ActivityAttributes {
    public typealias TimerStatus = ContentState
    
    public struct ContentState: Codable, Hashable {
        var endTime: Date
    }
    
    var timerName: String
}

Widget.swift

import ActivityKit
import WidgetKit
import SwiftUI

struct TimerActivityView: View {
    let context: ActivityViewContext<TimerAttributes>
    
    var body: some View {
        VStack {
            Text(context.attributes.timerName)
                .font(.headline)
            
            Text(context.state.endTime, style: .timer)
        }
        .padding(.horizontal)
    }
}

@main
struct Tutorial_Widget: Widget {
    let kind: String = "Tutorial_Widget"

    var body: some WidgetConfiguration {
        ActivityConfiguration(for: TimerAttributes.self) { context in
            TimerActivityView(context: context)
        } dynamicIsland: { context in
            DynamicIsland {
                DynamicIslandExpandedRegion(.leading) {
                // 2
                }
                DynamicIslandExpandedRegion(.trailing) {
                // 2
                }
                DynamicIslandExpandedRegion(.center) {
                // 2
                }
                DynamicIslandExpandedRegion(.bottom) {
                // 2
                }
            } compactLeading: {
             // 3
            } compactTrailing: {
             // 3
            } minimal: {
             // 4
            }
        }
    }
}

MainView.swift

import ActivityKit
import SwiftUI

struct MainView{
    @State private var activity: Activity<TimerAttributes>? = nil
}

extension MainView: View {
        var body: some View {
            VStack(spacing: 16) {
                Button("Start Activity") {
                    startActivity()
                }
    
                Button("Stop Activity") {
                    stopActivity()
                }
            }
            .buttonStyle(.borderedProminent)
            .controlSize(.large)
        }
    
        func startActivity() {
            let attributes = TimerAttributes(timerName: "Dummy Timer")
            let state = TimerAttributes.TimerStatus(endTime: Date().addingTimeInterval(60 * 5))
    
            do{
                activity = try Activity.request(attributes: attributes, contentState: state)
            }
            catch (let error) {
                print("")
                print("$$$$$$$$$$")
                print(error.localizedDescription)
                print(error)
                print(error.self)
                print("$$$$$$$$$$")
                print("")
            }
        }
    
        func stopActivity() {
            let state = TimerAttributes.TimerStatus(endTime: .now)
    
            Task {
                await activity?.end(using: state, dismissalPolicy: .immediate)
            }
        }
    
        func updateActivity() {
            let state = TimerAttributes.TimerStatus(endTime: Date().addingTimeInterval(60 * 10))
    
            Task {
                await activity?.update(using: state)
            }
        }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 23:10:25