Device Activity Center监控无法停止,屏蔽应用无法解锁求助
问题分析与解决方案
核心问题点
- ManagedSettingsStore实例不共享:BlockManager和Monitor各自初始化了独立的
ManagedSettingsStore,导致Monitor中修改的屏蔽设置无法覆盖BlockManager中设置的状态,解锁操作无效。 - DeviceActivitySchedule区间配置错误:当前schedule的
intervalStart设为当天0点,而非计时器启动的当前时间,导致监控区间逻辑不符合预期,intervalDidEnd可能无法正确触发。 - 停止监控的方法调用不精确:
stopMonitoring()中未指定要停止的具体活动名称,可能无法彻底终止目标监控任务。
修复后的代码
BlockManager修改
import Foundation import FamilyControls import DeviceActivity import ManagedSettings class BlockManager: ObservableObject { static let shared = BlockManager() // 共享同一个ManagedSettingsStore实例 let store = ManagedSettingsStore() private init() {} var selectionToDiscourage = FamilyActivitySelection() { willSet { let applications = newValue.applicationTokens let categories = newValue.categoryTokens store.shield.applications = applications.isEmpty ? nil : applications store.shield.applicationCategories = categories.isEmpty ? nil : ShieldSettings.ActivityCategoryPolicy.specific(categories, except: Set()) store.shield.webDomainCategories = categories.isEmpty ? nil : ShieldSettings.ActivityCategoryPolicy.specific(categories, except: Set()) } } func initiateMonitoring(timeInterval: TimeInterval) { let start = Date() let end = start.addingTimeInterval(timeInterval) // 正确设置监控区间:从当前时间开始到结束时间 let startComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: start) let endComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: end) let schedule = DeviceActivitySchedule( intervalStart: startComponents, intervalEnd: endComponents, repeats: false, warningTime: nil ) let center = DeviceActivityCenter() do { try center.startMonitoring(.once, during: schedule) } catch { print("Could not start monitoring \(error)") } } func stopMonitoring() { let center = DeviceActivityCenter() // 指定停止具体的活动名称,确保彻底终止监控 center.stopMonitoring(.once) // 主动重置屏蔽设置,确保解锁 resetShieldSettings() } // 新增方法:统一重置所有屏蔽设置 func resetShieldSettings() { store.shield.applications = nil store.shield.applicationCategories = nil store.shield.webDomainCategories = nil store.shield.webDomains = nil } } extension DeviceActivityName { static let once = Self("once") }
Monitor修改
import MobileCoreServices import ManagedSettings import DeviceActivity class Monitor: DeviceActivityMonitor { // 使用BlockManager共享的store实例,而非重新创建 private let store = BlockManager.shared.store override func intervalDidStart(for activity: DeviceActivityName) { super.intervalDidStart(for: activity) let model = BlockManager.shared let applications = model.selectionToDiscourage.applicationTokens store.shield.applications = applications.isEmpty ? nil : applications print("start monitoring") } override func intervalDidEnd(for activity: DeviceActivityName) { super.intervalDidEnd(for: activity) // 调用统一的重置方法,确保所有屏蔽设置被清除 BlockManager.shared.resetShieldSettings() print("end monitoring, shield reset") } override func eventDidReachThreshold(_ event: DeviceActivityEvent.Name, activity: DeviceActivityName) { super.eventDidReachThreshold(event, activity: activity) BlockManager.shared.resetShieldSettings() } }
额外注意事项
- 确保在AppDelegate或SceneDelegate中正确注册Monitor:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { DeviceActivityCenter.shared.monitor = Monitor() return true } - 测试时需确保应用已获得Screen Time权限,否则所有屏蔽操作无效。
内容的提问来源于stack exchange,提问作者Lorenzo Vecchio
相关产品推荐
相关产品推荐

