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
相关产品推荐
相关产品推荐

