I’ve updated to iOS 18.1 public beta when it released and I got the problem when I was in public beta 4 to rc and the problem never fixed with the time limit when I ask for more time it never give me more time it’s just says waiting for parent approval I have this problem until ios 18.1 RC can u fix it I’m on iPhone 11 pro max
Screen Time
RSS for tagShare and manage web-usage data, and observe changes made to Screen Time settings by a parent or guardian.
Posts under Screen Time tag
159 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I'd like to block the apps selected in FamilyActivityPicker individually when a certain threshold is met.
For example, let's say the threshold is 15 minutes, and I want to block both Photos and Freeform. If I spend 15 minutes on Photos, Photos should be blocked. Then, if I spend 15 minutes on Freeform, Freeform should also be blocked.
Currently, only Photos gets blocked after 15 minutes, but Freeform does not. How can I fix this problem so that each app is blocked individually when its respective 15-minute threshold is met?
Thank you in advance
File 1 :
class GlobalSelection {
static let shared = GlobalSelection()
var selection = FamilyActivitySelection()
private init() {}
}
extension DeviceActivityName{
static let daily = Self("daily")
}
@objc(DeviceActivityMonitorModule)
class DeviceActivityMonitorModule: NSObject {
private let store = ManagedSettingsStore()
@objc
func startMonitoring(_ limitInMinutes: Int) {
let schedule = DeviceActivitySchedule(
intervalStart: DateComponents(hour: 0, minute: 0),
intervalEnd: DateComponents(hour: 23, minute: 59),
repeats: true
)
let threshold = DateComponents(minute: limitInMinutes)
var events: [DeviceActivityEvent.Name: DeviceActivityEvent] = [:]
// Iterate over each selected application's token
for token in GlobalSelection.shared.selection.applicationTokens {
// Create a unique event name for each application
let eventName = DeviceActivityEvent.Name("dailyLimitEvent_\(token)")
// Create an event for this specific application
let event = DeviceActivityEvent(
applications: [token], // Single app token
threshold: threshold
)
// Add the event to the dictionary
events[eventName] = event
}
// Register the monitor with the activity name and schedule
do {
try DeviceActivityCenter().startMonitoring(.daily, during: schedule, events: events)
print("24/7 Monitoring started with time limit : \(limitInMinutes) m")
} catch {
print("Failed to start monitoring: \(error)")
}
}
@objc
static func requiresMainQueueSetup() -> Bool {
return true
}
}
FIle 2 :
class DeviceActivityMonitorExtension: DeviceActivityMonitor {
let store = ManagedSettingsStore()
var blockedApps: Set<ApplicationToken> = []
func scheduleNotification(with title: String) {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
if granted {
let content = UNMutableNotificationContent()
content.title = "Notification" // Using the custom title here
content.body = title
content.sound = UNNotificationSound.default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) // 5 seconds from now
let request = UNNotificationRequest(identifier: "MyNotification", content: content, trigger: trigger)
center.add(request) { error in
if let error = error {
print("Error scheduling notification: \(error)")
}
}
} else {
print("Permission denied. \(error?.localizedDescription ?? "")")
}
}
}
// Function to retrieve selected apps
func retrieveSelectedApps() -> FamilyActivitySelection? {
if let sharedDefaults = UserDefaults(suiteName: "group.timelimit.com.zerodistract") {
// Retrieve the encoded data
if let data = sharedDefaults.data(forKey: "selectedAppsTimeLimit") {
// Decode the data back into FamilyActivitySelection
let decoder = JSONDecoder()
if let selection = try? decoder.decode(FamilyActivitySelection.self, from: data) {
return selection
}
}
}
return nil // Return nil if there was an error
}
override func intervalDidStart(for activity: DeviceActivityName){
super.intervalDidStart(for: activity)
scheduleNotification(with: "Interval did start")
scheduleNotification(with: "\(retrieveSelectedApps())")
}
override func intervalDidEnd(for activity: DeviceActivityName) {
super.intervalDidEnd(for: activity)
}
override func eventDidReachThreshold(_ event: DeviceActivityEvent.Name, activity: DeviceActivityName) {
super.eventDidReachThreshold(event, activity: activity)
// Notify that the threshold is met
scheduleNotification(with: "Threshold met")
// Retrieve the selected apps
if let selectedApps = retrieveSelectedApps() {
// Extract the app token identifier from the event name
let appTokenIdentifier = event.rawValue.replacingOccurrences(of: "dailyLimitEvent_", with: "")
// Iterate over the selected application tokens
for appToken in selectedApps.applicationTokens {
// Convert the app token to a string representation (or use its debugDescription)
let tokenString = "\(appToken)"
// Check if the app token matches the token identifier in the event name
if tokenString == appTokenIdentifier {
blockedApps.insert(appToken)
// Block only the app associated with this event
store.shield.applications = blockedApps
scheduleNotification(with: "store.shield.applications = blockedApps is reached")
break
}
}
} else {
scheduleNotification(with: "No stored data for selectedAppsTimeLimit")
}
}
override func intervalWillStartWarning(for activity: DeviceActivityName) {
super.intervalWillStartWarning(for: activity)
// Handle the warning before the interval starts.
}
override func intervalWillEndWarning(for activity: DeviceActivityName) {
super.intervalWillEndWarning(for: activity)
// Handle the warning before the interval ends.
}
override func eventWillReachThresholdWarning(_ event: DeviceActivityEvent.Name, activity: DeviceActivityName) {
super.eventWillReachThresholdWarning(event, activity: activity)
// Handle the warning before the event reaches its threshold.
}
}
I need some assistance with the Screen Time API’s DeviceActivityReport extension. I know the extension is sandboxed but I need the data inside my app. Jomo is currently doing this so it’s not impossible. I see they’re saying it’s an estimate which is about 5 - 10 off of the actual screen time, but how are they doing this?
Any attempt to store the screen time data inside some sort of database or UserDefaults always fails of course due to the sandbox.
Any advice would be greatly appreciated!
Hello, I'm currently facing some technical difficulties in implementing features related to application restrictions using the ScreenTime API.
In our app, we allow users to set up restrictions for specific apps and app categories, with scheduled times and days (for example, Mondays and Thursdays, from 2pm to 5pm). The blocking sessions must run independently and simultaneously, allowing different sets of applications to be restricted at different times. However, I ran into two main problems:
1. Applying restrictions in the DeviceActivityMonitor extension:
Although I can enable and disable restrictions, I haven't found an effective way to apply multiple FamilyActivitySelections directly in the DeviceActivityMonitor extension. The extension has to manage different blocking sessions independently, restricting different sets of applications and categories simultaneously or separately.
I would like to know if it is possible to transmit this list of selected applications via UserDefaults or CoreData to the extension in order to facilitate this integra
To better illustrate, here is a snippet of the code I am using:
import Foundation
import FamilyControls
import ManagedSettings
import DeviceActivity
class AppBlockManager: ObservableObject {
private let store = ManagedSettingsStore()
private let center = DeviceActivityCenter()
@Published var activitySelection: FamilyActivitySelection
private var activityName: DeviceActivityName
private var schedule: DeviceActivitySchedule
init(selection: FamilyActivitySelection, activityName: DeviceActivityName, schedule: DeviceActivitySchedule) {
self.activitySelection = selection
self.activityName = activityName
self.schedule = schedule
}
func startBlock() {
do {
try center.startMonitoring(activityName, during: schedule)
if let applications = activitySelection.applications.isEmpty ? nil : activitySelection.applicationTokens {
store.shield.applications = applications
}
if let categories = activitySelection.categories.isEmpty ? nil : activitySelection.categoryTokens {
store.shield.applicationCategories = ShieldSettings
.ActivityCategoryPolicy
.specific(categories)
store.shield.webDomainCategories = ShieldSettings
.ActivityCategoryPolicy
.specific(categories)
}
if let webDomains = activitySelection.webDomains.isEmpty ? nil : activitySelection.webDomainTokens {
store.shield.webDomains = webDomains
}
} catch {
print("Error starting monitoring: \(error)")
}
}
func stopBlock() {
store.shield.applications = nil
store.shield.webDomains = nil
store.shield.applicationCategories = nil
store.shield.webDomainCategories = nil
center.stopMonitoring([activityName])
}
}
Currently, this AppBlockManager is part of the main app target, not within the DeviceActivityMonitor extension, which is currently empty. With this configuration, I can only have one blocking session active at a time, and when it is deactivated, all restrictions are removed. I tried using different ManagedSettingsStore instances, each named individually, but without success.
2. Problems with scheduling restrictions:
Currently, when setting up scheduled monitoring via DeviceActivitySchedule, the restrictions are activated immediately, ignoring the specific times scheduled (e.g. starting at 2pm and ending at 5pm). I need the schedule to work correctly, applying the restrictions only during the defined periods.
Alternatively, I've considered running a background task that checks whether active sessions (up to a maximum of 3) should apply the restrictions at that time, but I'm still looking for a more suitable solution.
In view of these challenges, I would like some guidance on the following points:
What would be the best way to configure the DeviceActivityMonitor extension to receive and apply different FamilyActivitySelections, ensuring that the blocking sessions are independent and can run simultaneously?
Is there a recommended approach to ensure that restrictions scheduled via DeviceActivitySchedule are applied and removed according to the times and days defined by the user, ensuring that applications are restricted only during the scheduled periods?
ActivityCategoryPolicy.all(except: allowList) blocks all apps, even the ones that should be exempted
Hello fellow Screen Time developers!
I have bee experimenting with the ActivityCategoryPolicy.all(except: allowList) API of the ManagedSettings framework in order to provide a digital detox feature to my app, where ALL apps would be blocked, except some important ones (phone, messages, maps).
The apps to be exempted can be configured by the user via the FamilyActivitySelection().
However, I am experiencing a strange bug, where all apps are restricted / blocked, even the ones that are set to be exempted and are part of the allowList Set.
Instead of not restricting allowed apps at all, these apps are restricted with a generic shield (screenshot below) – a concrete shield is not requested for them from my ShieldConfigurationDataSource.
I have also filed a radar under this number, attached is a minimalistic sample project and video that shows how to reproduce this: FB15500605
(no response so far)
I have also seen other people report on this issue, but couldn't find any useful information there:
https://forums.developer.apple.com/forums/thread/750988
https://forums.developer.apple.com/forums/thread/762287
Thanks a lot for your help, and have a nice day!
Why is my screen time doing this??? I’ve literally been on my phone about 30 mins today but it’s saying I’ve been on it all night. but it’s all grey lines and I can’t look at what it is?
Hello,
I think it is quite a common use-case to open the parent app that owns the ShieldActionDelegate when the user selects an action in the Shield.
There are only three options available that we can do in response to an action:
ShieldActionResponse.none
ShieldActionResponse.close
ShieldActionResponse.defer
It would be great if this new one would be added as well:
ShieldActionResponse.openParentApp
While finding a workaround for now, the problem is that the ShieldActionDelegate is not a normal app extension. That means, normal tricks do not work to open the parent app from here.
For example, UIApplication.shared.open(url) does not work because we can’t access UIApplication from the ShieldActionDelegate unfortunately.
NSExtensionContext is also not available in the ShieldActionDelegate unfortunately, so that’s also not possible.
There are apps however, that managed to find a workaround, in my research I stumbled across these two:
https://apps.apple.com/de/app/applocker-passcode-lock-apps/id1132845904?l=en-GB
https://apps.apple.com/us/app/app-lock/id6448239603
Please find a screen recording (gif) attached.
Their workaround is 100% what I’m looking for, so there MUST be a way to do so that is compliant with the App Store guidelines (after all, the apps are available on the App Store!).
I had documented my feature request more than 2 years ago in this radar as well: FB10393561
Hello
I updated my iPhone 13 to iOS 18 a few days ago and the last two nights, it indicated that my screen was on whilst I had actually switched my phone off for the night.
Last night I made sure to close all apps before I switched it off but Screen Time still says that my screen was on.
Is there a way to fix this so as to have screen time that actually corresponds to my screen time?
I’ve seen other users experiencing the same problem but haven’t found a solution.
Thanks!
Hello fellow Screen Time Fans!
I am encountering a strange problem since I started working with the Screen Time framework, and I don’t know what I’m doing wrong:
Imagine the app has two ManagedSettingsStores:
one to block apps during work hours (let’s say from 9am to 5pm) and one to block apps in the evening (let’s say from 5:30pm till midnight).
Imagine, the user has blocked Instagram in both.
When the user has Instagram open at 4:59pm it shows the Block during Work Hours Shield (so far, so good).
At 5pm, the shield is removed, and the user can use Instagram.
Then, at 5:30 the a shield is activated again: this time, the Instagram token is added to the evening store.
However, there is no new ShieldConfiguration requested from the ShieldConfigurationDataSource.
Instead, the previous shield from the work hour block is re-used and shown.
To me, it appears that the Framework does not request new shields, when the token is moved from one store to another while the app remains in foreground.
The Shield is only re-rendered when the user closes the shielded app and re-opens it.
This is really confusing behavior and I would like to fix it.
Did anyone here encounter something similar, and has a suggestion or workaround?
My feedback is also documented in FB14237883.
Core Data not returning results in ShieldConfiguration Extension, but works fine in other extensions
Hi everyone,
I’m using Core Data in several extensions (DeviceActivityMonitor, ShieldAction, and ShieldConfiguration). It works perfectly in DeviceActivityMonitor and ShieldAction. I’m able to successfully fetch data and log the correct count using a fetch request.
However, when I try the same setup in the ShieldConfiguration extension, the fetch request always returns 0 results. The CoreData and App Group setup appears to be correct since the first two extensions fetch the expected data.
I’ve also previously tested storing the CoreData objects separately in a JSON-FIle using FileManager and it worked without issues—though I’d prefer not to handle manual encoding/decoding if possible.
The documentation mentions that the extension runs in a sandbox, restricting network requests or moving sensitive content. But shouldn’t reading data (from a shared App Group, for instance) still be possible within the sandbox, as it is the case with the Files, what is the difference there? In my case, I only need to read the data, as modifications can be handled via ShieldActionExtension.
Any help would be greatly appreciated!
Hi, I noticed that all my apps are sometimes blocked even if I don’t have set up screen time for them. How can I fix it?
I use a parental control app and it should block apps only if I enable child mode, but after the iOS 18 update, it blocks apps even when I am still in parent mode.
Family activity picker looses icon and incudes parent apps after 20 seconds...and you never see the kids icons again until you reboot. Any ideas?
family controls authorized on both apps
Share across devices activated
Web & activity activated.
Before...
...and after 22 seconds.
A few weeks ago, I submitted a request for the Family Controls & Personal Device Usage Entitlement to enable my app to access the Managed Settings and Device Activity frameworks in the Screen Time API. The app is nearly complete, with the only remaining component being the Family Controls capability.
As of now, I haven’t received a response regarding the request. I’m wondering if anyone else has experienced a similar situation or can provide insight into the following:
• How long does it typically take to receive feedback on this type of entitlement request?
• Is there a way to check if a request is still active and under review?
• Is a finished website required for the entitlement to be granted?
Any information or guidance would be greatly appreciated!
Tl:dr What are some reasons my bundleIDs aren't showing up and does anyone have good resources to setup the screentime API/DeviceActivityMonitorExtension?
I'm working on an iOS app that uses the FamilyControls and DeviceActivity frameworks to monitor and restrict app usage. The app allows users to select apps and set usage limits. When a limit is reached, a DeviceActivityMonitorExtension should block the selected apps.
My App setup: Have a model that is called when users select apps to manage these app bundle IDs are then serialized and sent to the Device Monitor Extension via App Group so it can be used when the event threshold is reached. Cant use Application Tokens because they are not serielizable and cant be passed to the extension.
Problem: While testing, I’m unable to retrieve the bundleIdentifier and localizedDisplayName from the Application objects after selecting apps. Instead, these properties are nil or empty, preventing me from saving the bundle IDs to share with the extension via App Groups.
Assumptions: I suspect this issue is due to missing the com.apple.developer.screentime.api entitlement, which might be required to access these properties even during development. I've requested for the entitlement but its still under review.
Key Code Snippets:
Authorization Request:
class ScreenTimeManager: ObservableObject {
static let shared = ScreenTimeManager()
@Published var isAuthorized: Bool = false
func requestAuthorization() async {
do {
try await AuthorizationCenter.shared.requestAuthorization(for: .individual)
DispatchQueue.main.async {
self.isAuthorized = AuthorizationCenter.shared.authorizationStatus == .approved
print("Authorization status: \(AuthorizationCenter.shared.authorizationStatus)")
}
} catch {
DispatchQueue.main.async {
print("Authorization failed: \(error.localizedDescription)")
self.isAuthorized = false
}
}
}
}
Accessing bundleIdentifier:
print("addAppGroup() Called")
let managedApps = selection.applications.compactMap { application -> ManagedApp? in
guard let token = application.token else {
print("No token for application: \(application)")
return nil
}
let app = Application(token: token)
print("New Application instance: \(app)")
guard let bundleID = app.bundleIdentifier, !bundleID.isEmpty else {
print("Bundle identifier is empty or nil for application: \(app)")
return nil
}
let displayName = app.localizedName ?? "Unknown App"
print("Processing application with bundleIdentifier: '\(bundleID)' and displayName: '\(displayName)'")
return ManagedApp(
bundleIdentifier: bundleID,
applicationToken: token,
localizedDisplayName: displayName
)
}
if managedApps.isEmpty {
print("No managed apps created. Exiting addAppGroup().")
return
}
// Continue with creating DeviceActivityEvent...
}
Logs - Shows application token but never bundleID or LocalizedDisplayname
Application(bundleIdentifer: nil, token: Optional(128 byte <TOKEN_PRESENT>), localizedDisplayName: nil)
What I've Tried:
Ensured Screen Time is enabled on the device.
Verified App Group configuration in both app and extension.
Checked that authorization is being requested and the status is .approved.
Cleaned and rebuilt the project.
Questions:
Is the com.apple.developer.screentime.api entitlement required to access bundleIdentifier and localizedDisplayName when using .individual authorization?
Is there a way to access these properties without the entitlement, or am I missing a configuration step?
Has anyone faced a similar issue and found a solution?
Lastly, is there a good place for additional resources on the screentime API??
Made a screen time password a little while ago and recently updated to ios 18. Went to turn it off and couldn’t remember the password. There was not forgot password option and now I’m on my like millionth attempt to guess the password.
I’m developing a self-management app using Family Controls, but I’ve encountered a FamilyActivityPciker's crash due to an XPC(or UIRemoteView) issue when there are too many tokens(maybe 200+ items) in a category. This makes bad UX, so I’m looking for a workaround.
(I guess that the crash reason is cross process memory limitations, such as App Extension 50MB memory limitation.)
A lot of web domains contribute to increase the number of tokens, However, even after clearing Safari’s browsing history, the tokens displayed in the FamilyActivityPicker remains unchanged.
Is there any workaround that a 3rd party developer can implement to address this issue? prevent FamilyActivityPicker crashes or reduce the number of web domain tokens?
For example, if there’s a way to reset the web domain tokens shown in FamilyActivityPicker from the Settings app, I could offer a help to users.
Does anybody have ideas?
Expanding SNS Category (29 items)
It succeeded.
Expanding Productivity & Finance (214 items)
It failed. The screen froze, then appears blank. When the number of items is around 100, the crash rate is 50%, but when the items are over 200, the crash rate is 100%.
Search Bar Problem
The search bar also has same problem. If the number of search results are small, it works good without any blank, but if there are a lot of search results (200+), the XCP crashes and the screen appears blank.
Code to Reproduce
import SwiftUI
import FamilyControls
struct ContentView: View {
@State private var selection = FamilyActivitySelection()
@State private var isPickerPresented: Bool = false
var body: some View {
VStack {
Button("Open Picker") {
isPickerPresented = true
}
}
.familyActivityPicker(isPresented: $isPickerPresented, selection: $selection)
}
}
Steps to Reproduce
Prepare a category that has 200+ items
Try to open the category in the picker
The screen will freeze, then appears blank.
Errors in Console
[u EDD60B83-5D2A-5446-B2C7-57D47C937916:m (null)] [com.apple.FamilyControls.ActivityPickerExtension(1204)] Connection to plugin interrupted while in use.
AX Lookup problem - errorCode:1100 error:Permission denied portName:'com.apple.iphone.axserver' PID:2164 (
0 AXRuntime 0x00000001d46c5f08 _AXGetPortFromCache + 796
1 AXRuntime 0x00000001d46ca23c AXUIElementPerformFencedActionWithValue + 700
2 UIKit 0x0000000256b75cec C01ACC79-A5BA-3017-91BD-A03759576BBF + 1527020
3 libdispatch.dylib 0x000000010546ca30 _dispatch_call_block_and_release + 32
4 libdispatch.dylib 0x000000010546e71c _dispatch_client_callout + 20
5 libdispatch.dylib 0x00000001054765e8 _dispatch_lane_serial_drain + 828
6 libdispatch.dylib 0x0000000105477360 _dispatch_lane_invoke + 408
7 libdispatch.dylib 0x00000001054845f0 _dispatch_root_queue_drain_deferred_wlh + 328
8 libdispatch.dylib 0x0000000105483c00 _dispatch_workloop_worker_thread + 580
9 libsystem_pthread.dylib 0x0000000224f77c7c _pthread_wqthread + 288
10 libsystem_pthread.dylib 0x0000000224f74488 start_wqthread + 8
)
Error acquiring assertion: <Error Domain=RBSAssertionErrorDomain Code=2 "Specified target process does not exist" UserInfo={NSLocalizedFailureReason=Specified target process does not exist}>
Hi everyone,
I'm working on a Swift application and trying to determine whether an application has exceeded its limit based on an ApplicationToken. I have the following function to check if the current app's token matches any of the tokens stored when the app limit is reached:
private func isAppLimitExceeded(for application: Application?) -> Bool {
guard let application = application, let appToken = application.token else { return false }
let exceededTokens = configManager.getAppLimitExceededTokens()
return exceededTokens.contains { exceededToken in
appToken == exceededToken
}
}
The function configManager.getAppLimitExceededTokens() returns a list of [ApplicationToken] that were saved in UserDefaults when an app limit is reached. The goal is to use the isAppLimitExceeded method to verify if the current shield for the app is triggered due to a limit/threshold being exceeded.
This function is part of a class that conforms to the ShieldConfigurationDataSource protocol:
class ShieldConfigurationExtension: ShieldConfigurationDataSource {
// ...
}
My concern is whether comparing two ApplicationToken instances using == is a reliable method for determining if they are equal.
Are ApplicationToken objects guaranteed to be comparable with == out of the box, or do I need to implement Equatable or another method of comparison?
Could there be issues with tokens stored in UserDefaults not matching due to reference or serialization differences?
Any guidance on how to ensure proper comparison of these tokens would be appreciated!
Thanks!
Our app uses a 24-hour DeviceActivityMonitor repeating schedule to send users notifications for every hour of screen time they spend on their phone per day. Notifications are sent from eventDidReachThreshold callbacks at 1, 2, 3, etc, hour thresholds to keep them aware of their screen time.
We have recently received an influx of emails from our users that after updating to iOS 17.6.1 their DeviceActivityMonitor notifications are saying their screen time was much higher than what is shown in DeviceActivityReport and their device's Screen Time settings.
These users have disabled "Share Across Devices" - but I suspect the DeviceActivityMonitor is still getting screen time from their other devices even though that setting is turned off.
Has anybody else noticed this, understands what is causing this, or could recommend a fix that we can tell our users to do?
I've submitted several requests for Family Controls Distribution access for all of my app targets over two weeks ago and have not gotten any response. The app I've been working on for over a year is finally ready to beta test to 200+ waitlisted users but this final roadblock is killing me! Anyone know what to do? Is there anyone else I could reach out to other than the apple request form to get help with this? Thank you!
I want to create an app to control a child's device. As I understand it, I need to follow this logic:
I have one app for both the child and the parent.
For the child, I request authorization with the following code:
try await AuthorizationCenter.shared.requestAuthorization(for: .child)
For the parent, I show functions like:
familyActivityPicker
Are these settings automatically applied to the child's device, or do I need to send a silent push notification to apply the new settings? Additionally, how can I get statistics from the child's device to the parent's device?