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

如何检测Screen Time进程崩溃?Swift TabView切换异常技术问询

检测Screen Time进程崩溃的可行方案

针对SwiftUI TabView中快速切换标签页导致Screen Time进程崩溃、报告空白的问题,以下是几种无需每次切换强制刷新的崩溃检测方案:

1. 包装DeviceActivityReport监听视图生命周期

通过UIViewRepresentable包装原生DeviceActivityReport,监听其底层视图的window绑定状态——进程崩溃会导致视图突然脱离window,以此作为崩溃信号:

struct DeviceActivityReportWrapper: UIViewRepresentable {
    let context: DeviceActivityReport.Context
    let filter: DeviceActivityFilter?
    var onCrashDetected: () -> Void

    func makeUIView(context: Context) -> some UIView {
        let reportView = DeviceActivityReportUIView(context: self.context, filter: self.filter)
        // 监听视图的window绑定变化
        reportView.observe(\.window, options: [.new, .old]) { _, change in
            if change.oldValue != nil && change.newValue == nil {
                DispatchQueue.main.async {
                    self.onCrashDetected()
                }
            }
        }
        return reportView
    }

    func updateUIView(_ uiView: UIViewType, context: Context) {}
}

在标签页视图中使用该包装器,仅在检测到崩溃时触发刷新:

struct Tab2View: View {
    @State private var needsRefresh = false

    var body: some View {
        Group {
            if needsRefresh {
                DeviceActivityReport(Utils.weeklyContext, filter: Utils.filterWeekly)
                    .id(UUID())
            } else {
                DeviceActivityReportWrapper(context: Utils.weeklyContext, filter: Utils.filterWeekly) {
                    needsRefresh = true
                }
            }
        }
        .onAppear {
            if needsRefresh { needsRefresh = false }
        }
    }
}

2. 监听Screen Time授权状态突变

进程崩溃可能导致授权状态异常回落,通过监听DeviceActivityAuthorizationCenter的状态变化来检测崩溃:

struct TabContainerView: View {
    @State private var lastAuthStatus: DeviceActivityAuthorizationStatus = .authorized
    private let authCenter = DeviceActivityAuthorizationCenter.shared

    var body: some View {
        TabView {
            Tab1View()
                .tabItem { Label("Tab 1", systemImage: "1.circle.fill") }
            Tab2View()
                .tabItem { Label("Tab 2", systemImage: "2.circle.fill") }
        }
        .onReceive(authCenter.$authorizationStatus) { newStatus in
            if lastAuthStatus == .authorized && newStatus != .authorized {
                // 授权状态异常回落,判定为进程崩溃,触发全局刷新
                NotificationCenter.default.post(name: .refreshScreenTimeReports, object: nil)
            }
            lastAuthStatus = newStatus
        }
    }
}

// 扩展通知名
extension Notification.Name {
    static let refreshScreenTimeReports = Notification.Name("RefreshScreenTimeReports")
}

在各标签页视图中监听通知,仅在需要时刷新:

struct Tab2View: View {
    @State private var refreshId = UUID()

    var body: some View {
        DeviceActivityReport(Utils.weeklyContext, filter: Utils.filterWeekly)
            .id(refreshId)
            .onReceive(NotificationCenter.default.publisher(for: .refreshScreenTimeReports)) { _ in
                refreshId = UUID()
            }
    }
}

3. 基于视图渲染状态的可用性检查

在标签页切换后,通过定时器检查DeviceActivityReport的渲染尺寸——进程崩溃会导致视图无法正常渲染,尺寸为0:

struct Tab2View: View {
    @State private var isReportValid = true

    var body: some View {
        DeviceActivityReport(Utils.weeklyContext, filter: Utils.filterWeekly)
            .background(GeometryReader { geo in
                Color.clear.onAppear {
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                        // 尺寸异常判定为崩溃
                        if geo.size.width == 0 || geo.size.height == 0 {
                            isReportValid = false
                        }
                    }
                }
            })
            .id(isReportValid ? UUID() : UUID())
            .onAppear {
                if !isReportValid { isReportValid = true }
            }
    }
}

以上方案均仅在检测到崩溃时触发报告刷新,避免了每次切换标签页都重新加载完整报告的开销,与Jomo、Opal等应用的优化思路一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 20:33:15