I am developing a parental control app using Apple’s Screen Time API and FamilyControls Framework. My goal is to allow parents to remotely block apps on their child’s device from their own phone. Does anyone have any idea how I can achieve that?
Post
Replies
Boosts
Views
Activity
I am working on a SwiftUI app using the Screen Time API and the DeviceActivityReport view to display app usage data. My current implementation successfully shows daily app usage using a DeviceActivityFilter with the .daily(during:) segment. However, I need to filter this data to show app usage only for a specific time period during the day, e.g., 4:00 PM to 5:00 PM.
I created a DeviceActivityFilter with a .daily(during:) segment and passed a DateInterval for the desired time range:
let now = Date()
let startTime = calendar.date(bySettingHour: 16, minute: 0, second: 0, of: now)!
let endTime = calendar.date(bySettingHour: 17, minute: 0, second: 0, of: now)!
let timeInterval = DateInterval(start: startTime, end: endTime)
let filter = DeviceActivityFilter(
segment: .daily(during: timeInterval),
users: .all,
devices: .init([.iPhone])
)
I applied this filter to the DeviceActivityReport view:
DeviceActivityReport(context, filter: filter)
Even with the DateInterval set for the specific time range, the report still shows the total daily usage for each app, instead of restricting the results to the specified 1:00 PM to 5:00 PM range.
I have a app with two targets: a main DeviceActivityApp target and a DeviceReport target. In the DeviceReport target, I have a TotalActivityReport struct conforming to DeviceActivityReportScene. Inside its makeConfiguration method, I update a dynamically generated list of AppReport items. The list updates correctly in the DeviceReport target.
// Define which context your scene will represent.
let context: DeviceActivityReport.Context = .totalActivity
// Define the custom configuration and the resulting view for this report.
let content: (MonitorDeviceReport) -> TotalActivityViewFirst
@ObservedObject var activityData:ActivityData
func makeConfiguration(representing data: DeviceActivityResults<DeviceActivityData>) async -> MonitorDeviceReport {
// Reformat the data into a configuration that can be used to create
// the report's view.
var appList:[AppsReport]=[]
let totalActivityDuration = await data.flatMap { $0.activitySegments }.reduce(0, {
$0 + $1.totalActivityDuration
})
for await _data in data{
for await activity in _data.activitySegments{
for await category in activity.categories{
for await app in category.applications{
let name=app.application.localizedDisplayName ?? "No Name"
let bundleId=app.application.bundleIdentifier ?? "nil"
let duration=app.totalActivityDuration
let appIcon=app.application.token
let app=AppsReport(id:bundleId,duration:duration, name:name, icon:appIcon)
appList.append(app)
}
}
}
}
DispatchQueue.main.async {
activityData.list=appList
}
return MonitorDeviceReport(duration:totalActivityDuration, apps:appList)
}
}
public class ActivityData:ObservableObject{
@Published var list:[AppsReport]=[]
public static let shared = ActivityData()
}. // This is in MonitorReport target
However, I need to access this dynamic list in my MyApp target, specifically in ContentView.swift. I tried using an ObservableObject (ActivityData) to share the data between targets, but the list always appears empty in the MyApp target.
Here’s what I’ve tried so far:
Created a shared ActivityData instance using @Published
Passed the ActivityData instance to TotalActivityReport
Used dependency injection and a singleton pattern for ActivityData
Verified that makeConfiguration updates the list correctly in DeviceReport
What could I be missing? How can I correctly share and access this data across targets?
I'm working with the Screen Time API in iOS and have successfully implemented the following:
Granted Screen Time Permission: The app asks for and obtains Screen Time permissions without any issues.
Blocked Specific Apps: Using FamilyActivitySelection, I can block access to certain apps.
Monitoring Device Activity: With DeviceActivityCenter().startMonitoring(), I’m able to successfully start monitoring.
DeviceActivityCenter().startMonitoring(.myActivity, during: schedule)
Now, I’m wondering if there’s a way to detect exactly which app the user opens, so I can fire an API from my own app based on that event.
Is this kind of real-time app usage detection possible with the Screen Time API? If so, how might it be implemented?