Hi everyone,
I'm currently working with the Screen Time API, specifically trying to figure out the best way to pause an active, repeating schedule without disrupting future schedules. Here's the scenario:
I have a repeating schedule set from 10:00 AM to 8:00 PM daily. If I need to pause the schedule temporarily, my current approach involves stopping monitoring, clearing all restrictions, and then setting a new schedule for the remaining time after the pause. However, this method cancels the repeating schedule entirely, which causes issues when the schedule is supposed to restart the next day at 10:00 AM. Instead, it starts after the pause time, which isn’t what I want.
Challenges I'm Facing:
Maintaining Repeating Schedules:
How can I pause the schedule in a way that ensures it resumes correctly the next day at the intended time (10:00 AM)?
DeviceActivityMonitor Logic:
Is there a way to deactivate and reactivate the schedule through the DeviceActivityMonitor without fully stopping the monitoring? Ideally, I'd like to retain the original schedule, pause it, and then resume it seamlessly after the pause.
What I’ve Tried So Far:
I’ve attempted to store the necessary data in the App Groups shared container as a local file. In the DeviceActivityMonitor, I used the schedule's name to identify and retrieve the saved object, planning to use this data to reapply the shielding after the pause. Unfortunately, this approach exceeds the 6MB memory limit of the extension, which is another roadblock.
Given these issues, I’m unsure how to move forward. Are there any best practices or alternative approaches that could help manage this situation more effectively? Any insights or suggestions would be greatly appreciated!
Thanks in advance for your help.
I finally found a suitable solution, though it may not be the best approach. I'm storing the selection in shared UserDefaults with the Schedule ID as the key. This way, I can always retrieve the selected apps when I have the Schedule ID.
This solved the problem of not having access to the apps that should be restricted.
The other issue is actually pausing the monitoring, for which this solution is quite elegant:
- When the pausing action starts, all restrictions for this activity should be cleared, and the activity should no longer be monitored.
- Start a new activity with the identifier "pause+(oldID)" using the same selection and schedule times. The new schedule should contain a proper warningTime. Learn more about it here (it's not as simple as you might think): Apple Developer Documentation.
- In your DeviceActivityMonitor, your intervalDidStart(for activity:) function will now be called. But since the new schedule is started with the ID "pause+(oldID)", you can react to the name of the activity.
You can now add logic like this:
if !activity.rawValue.contains("pause+") {
startMonitoring()
}
This will ensure that monitoring is not started when the ID contains "pause".
- In your DeviceActivityMonitor, override the function intervalWillEndWarning(for activity:) and add logic like this:
override func intervalWillEndWarning(for activity: DeviceActivityName) {
super.intervalWillEndWarning(for: activity)
let activityName = activity.rawValue.contains("pause+") ? activity.rawValue.replacingOccurrences(of: "pause+", with: "") : activity.rawValue
// Clears the old monitoring and store
let center = DeviceActivityCenter()
let store = ManagedSettingsStore(named: .init(activity.rawValue))
// Start new schedule when the pausing reaches its end time
if let schedule = center.schedule(for: .init(rawValue: activity.rawValue)) {
center.stopMonitoring([.init(activity.rawValue)])
store.clearAllSettings()
// Start new monitoring
startMonitoring()
}
}
This way, you have successfully paused your schedule while maintaining the original begin and end times.