Device Activity

RSS for tag

Monitor web and app usage through custom time windows and events.

Posts under Device Activity tag

84 Posts

Post

Replies

Boosts

Views

Activity

How to Share and Access Dynamically Updating Data Across Different Targets?
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?
0
0
384
Nov ’24
Device activity report data View is hidding when change the tab
I am working on the device activity report. and fetched data is loading on the chart. I am developing app using TabbarController. when I go to another tab and come back to the chart screen, it disappears. Here, I am working on a storyboard using Swift language, and device activity reports can be fetched only with SwiftUI. So, the problem is with it? Following the current code. @State private var context: DeviceActivityReport.Context = .init(rawValue: "Daily Activity") @State private var report: DeviceActivityReport? @State private var filter = DeviceActivityFilter( segment: .daily( during: Calendar.current.dateInterval( of: .day, for: .now )! ) // users: .all // devices: .init([.iPhone, .iPad]) ) @State var isReload: Bool = false var body: some View { ZStack { if isReload { LoadingView(title: "Data is loading...") } else if let report = report { report } else { DeviceActivityReport(context, filter: filter) } } .onAppear { DispatchQueue.main.async { report = DeviceActivityReport(context, filter: filter) } } } struct LoadingView: View { var title: String = "Please wait..." var body: some View { HStack { ProgressView(title) .font(.system(size: 14, weight: .medium)) .progressViewStyle(.horizontal) .tint(Color(.darkGray)) .padding(8) } .background(Color(.white)) .cornerRadius(8) .clipped() } }
0
0
610
Nov ’24
Taking long time to load Device Activity Report
When I try to load the device activity report, it takes too long to load data. Is this because of development time? Will the problem be solved when the app is live on the App Store? If it does not depend on the development profile, then please give me a solution for the fast data loading in the device activity report extension. Thank you
0
1
411
Nov ’24
Premature DeviceActivityEvent Triggering
Our app monitors device usage and applies a shield when the set time limit is reached. Multiple DeviceActivitySchedules can be present, each with different time limits. To display notifications at 50% of the total limit for each DeviceActivitySchedule, we set a warning time at half of the total time. However, we occasionally receive premature event callbacks. For example, consider a schedule from 13:00 to 13:30 with a single event threshold at 10 minutes and a warning time of 5 minutes. The 'eventDidReachThreshold' callback is delivered prematurely, along with the 'eventWillReachThresholdWarning' callback, at 13:10. Additionally, in some cases, when one DeviceActivitySchedule ends and the next begins immediately, DeviceActivityEvents registered for the new DeviceActivitySchedule are delivered prematurely along with the schedule start callback. For example, consider there are two DeviceActivitySchedules from 12:00 to 13:00 and from 13:00 to 14:00, each with a limit of 10 minutes and a warning time of 5 minutes. When the first schedule ends and the next begins at 13:00, the 'eventDidReachThreshold' callbacks for the events registered in the second schedule are delivered prematurely, along with the 'intervalDidStart' callback.
1
0
403
Nov ’24
Can I Detect Which App the User Opens Using the Screen Time API?
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?
2
1
487
Dec ’24
How to force update data from child phone ? FamilyControls / Screen Time Api / DeviceActivity
The data displayed about a child’s apps can be outdated (DeviceActivityReport), leading to misinformation for the user. When I access the “Screen Time” section (for child in the parent device) in the iPhone settings, I see there is an update functionality to force load the actual data. I have tried various workarounds, such as attempting to force an update on the child’s device to call DeviceActivityReport and opening system settings, but none of these have been successful :( How can I implement something similar? Is there a way to force update this data ?
0
2
486
Nov ’24
Device Activity Monitor
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. } }
1
0
705
Oct ’24
Difficulty blocking and scheduling with the Screen Time API
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?
2
2
885
Oct ’24
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!
2
0
985
Oct ’24
DeviceActivityEvent with includesPastActivity = false, sometimes does not trigger callback
Sometimes when I schedule a DeviceActivityEvent with the includesPastActivity property set to false, the event is never triggered. I tried with thresholds of 20 seconds and 1 minute and both did not work. I submitted feedback with more details FB15220094. Is anyone else experiencing this issue ? or does anyone know about a fix ?
1
0
443
Nov ’24
DeviceActivityMonitor is overcounting screen time for users on iOS 17.6.1
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?
9
7
1.6k
Dec ’24
DeviceActivityMonitor event thresholds triggered together - what is the best way to log crashes / system terminations in the DeviceActivityMonitor extension?
I've been using DeviceActivityMonitor for 2 years, and recently noticed the following issue, starting in iOS 17.5 (another user also reported here). For a sizable percentage of my users, device activity event thresholds get triggered together. My app sends notifications for every hour of screen time during the DeviceActivitySchedule using event thresholds. Often users will get, for example, the 1, 2, and 3 hour screen time notifications all at the same time. I have a hypothesis for why this is happening: the system sometimes terminates the app extension for various reasons, one being if the 6MB memory limit is reached. It seems as though the retry policy is to retry the failed threshold at the next event threshold. And if the following threshold also fails, they can pile up until the next one succeeds. I think this is a new retry policy since iOS 17, and I believe this because: There used to be a bug where the same threshold was triggered multiple times in a row, indicating that the failed threshold was retried immediately. This bug is no longer around and it's been replaced by the one I am reporting. According to my logs, thresholds that get triggered together are also called earlier when they are supposed to be called - but the callback function does not complete. So this indicates that the threshold isn't just called late, but that it is called once and then retried again later. If anyone could answer the following questions I'd be super grateful: Is there ANY way to log when the system terminates the app extension and for what reason? And not just on my own device, but for all our users in production (because it's hard to reproduce this issue, as it only happens for some portion of our users). Maybe some kind of crash report or failure callback that will allow my to ping my server? Could anyone at Apple could confirm my hypothesis about the new retry policy causing this issue?
1
5
716
Nov ’24
Schedule a Screenlock for a time in the future? (ScreenTime API))
Hello! I'm currently making an app that requires the ability to activate a screenlock for a point in the future. I currently have my project setup so that I can set a screenlock through a DeviceActivityMonitorExtension (DAM) but regardless of the time interval I use for intervalDidStart and intervalDidEnd the screenlock just seems to apply instantly. I'm under the impression that I'm missing something outside of just passing the interval to the DAM functions. Has anyone accomplished this? Thank you!
1
0
517
Nov ’24
[iOS 18 Beta 4] DeviceActivityMonitor extension is more likely to deadlock
Hi there, My app uses all the Screen Time API's with individual FamilyControls authorization. I've been using the API's for over 2 years (since they came out). In iOS 18 Beta (maybe started in Beta 3?), I've been experiencing random issues. I tracked it down to where it seems like DeviceActivityMonitor extension is more likely to deadlock in iOS 18. To reproduce: when DeviceActivityMonitorExtension.intervalDidEnd gets called, IF you call DeviceActivityCenter.startMonitoring for that SAME DeviceActivityName from the DeviceActivityMonitorExtension , the startMonitoring call deadlocks (if I pause debugger, it does not advance past DeviceActivityCenter.startMonitoring). The bug is reported in FB14664238. It also contains a sample project where you can reproduce this. I also note in the comment section that this is not the only way to encounter this problem. My application code (which is a lot more complicated) seems to deadlock on calling DeviceActivityCenter.activities. As a result, there seems to be an "overall trend" where, due to some changes, DeviceActivityMonitor extension is more likely to deadlock. The steps are not reproducible on iOS 17.6. This is built using Xcode 17.4. Thank you! 🙏
1
3
734
Mar ’25
Device Activity Report only for Selected Apps
I want to display device activity reports for particular selected apps. for getting a daily basis app uses time. Now, what is happening? there are 10 apps selected from the family activity picker but some apps are displayed in the list. I need all 10 apps or more that I will choose from the family activity picker. The bellow code is used for fetching reports. var body: some View { VStack { DeviceActivityReport(context, filter: filter) } } bellow code is used for the filter @State public var filter = DeviceActivityFilter() init(selectedApps: Set<ApplicationToken>, selectedCategories: Set<ActivityCategoryToken>, selectedWebDomains: Set<WebDomainToken>) { self.selectedApps = selectedApps self.selectedCategories = selectedCategories self.selectedWebDomains = selectedWebDomains self.filter = DeviceActivityFilter( segment: .daily( during: Calendar.current.dateInterval( of: .weekOfYear, for: .now )! ), users: .all, devices: .init([.iPhone]), applications: selectedApps, categories: selectedCategories, webDomains: selectedWebDomains ) } You can see we selected 3 apps from family activity picker but we getting 2 apps from DeviceActivityReport extension following code is for device activity report extension let context: DeviceActivityReport.Context = .totalActivity // Define the custom configuration and the resulting view for this report. let content: (ActivityReport) -> TotalActivityView func makeConfiguration(representing data: DeviceActivityResults<DeviceActivityData>) async -> ActivityReport { // Reformat the data into a configuration that can be used to create // the report's view. var res = "" var list: [AppDeviceActivity] = [] let totalActivityDuration = await data.flatMap { $0.activitySegments }.reduce(0, { $0 + $1.totalActivityDuration }) for await d in data { res += d.user.appleID!.debugDescription res += d.lastUpdatedDate.description for await a in d.activitySegments{ res += a.totalActivityDuration.formatted() for await c in a.categories { for await ap in c.applications { if let apptoken = ap.application.token { let appName = (ap.application.localizedDisplayName ?? "nil") let bundle = (ap.application.bundleIdentifier ?? "nil") let duration = ap.totalActivityDuration let numberOfPickups = ap.numberOfPickups let app = AppDeviceActivity(appToken: apptoken, id: bundle, displayName: appName, duration: duration, numberOfPickups: numberOfPickups) list.append(app) } } } } } return ActivityReport(totalDuration: totalActivityDuration, apps: list) }
4
0
974
Feb ’25
Tokens change without reason after updating to iOS 17.5.1
Some of our users encounter an issue after updating their iPhone/iPad to iOS 17.5.1. The tokens passed in the Shield Configuration extension don't match the tokens they selected in my app using the FamilyPicker before updating to iOS 17.5.1. It seems the tokens changed for no reason. My app can't match the token from the ShieldConfigurationDataSource to any tokens stored on my end, causing my shield screens to turn blank. The same applies to tokens in the Device Activity Report extension. The only workaround I've found is to tell affected users to unselect and reselect apps and websites to block in my app. This gets them new tokens from the FamilyActivityPicker, which solves the issue. However, for some users, the bug reoccurs a few days later. Tokens seem to change again, causing the same issue in the Shield Configuration extension. I am not able to reproduce the issue on my test devices so I have no sysdiagnose to attach. However, this issue is affecting other screen time apps: https://developer.apple.com/forums/thread/732845 https://forums.developer.apple.com/forums/thread/756440 FB14082790 FB14111223 A change in iOS 17.5.1 must have triggered this behaviour. Could an Apple engineer give us any updates on this?
27
6
2.2k
Aug ’25
Screentime API new issues on iOS 17.4.1 and 17.5.1
Hi, I have a released screentime app ScreenZen. The last few days I've seen a disturbing spike in bug reports coming from people with 17.4.1 and 17.5.1 phones with no update to the app itself. People reported they saw the issue immediately after updating their iOS version. Unfortunately it is not replicable on all phones with those versions, so we haven't been able to replicate it on our test phones. It appears the issue is the ApplicationToken passed into ShieldActionExtension and ShieldConfigurationExtension does not match any of the ApplicationTokens that the user selected to block through FamilyControls. (The selected ApplicationTokens are being loaded through a group UserDefaults and they are indeed being loaded in the ShieldActionExtension in the bug reports).This is preventing the app from loading the correct settings and handling the blocking accordingly. I am trying to isolate this better with a new release with better logging, but would appreciate any help on this issue.
3
6
2.4k
Jul ’25
Device Activity Reports are returning a blank screen in release mode
There is an inconsistent issue when views are rendered from the Device Activity Report Extension. This issue is noticeable only on release versions and it works fine in debug mode. Around 80% of the times, the Report Views return blank screen and this is only the case when a weekly/monthly filter is used. Although, it works as expected for daily report views. My questions are: How are all the Report Activity Views working fine in debug mode but not in release mode? How the daily activity filter works fine in the release mode but the weekly/monthly filters don't work? Is this because of a memory limit issue in the extension? As of now, I have the family-controls(distribution) entitlement only for the app and for the extensions I only have family-controls(development) entitlement. Do I need to request for family-controls(Distribution) entitlement even for the extensions? I have seen threads on the forum mentioning the blank screen issue associated with the DeviceActivityReport but haven't found a solution to it. Any suggestions/feedback would be of great help, thanks.
3
2
1.1k
Jun ’25
ShieldConfigurationExtension not working
I created a ShieldConfigurationExtension in Xcode 14.3 with File > New > Target > ShieldConfigurationExtension. This created the extension with all the necessary Info.plist values (correct NSExtensionPrincipalClass, etc.), with the extension included in embedded content in the host app target. No matter what I try, the extension is not getting invoked when I shield applications from my host app. The custom UI does not show as the shield, and looking at the debugger, an extension process is never invoked. I am shielding categories like this: let managedSettings = ManagedSettingsStore() ... managedSettings.shield.applicationCategories = .all() And my extension code overrides all the ShieldConfigurationDataSource functions. class ShieldConfigurationExtension: ShieldConfigurationDataSource { override func configuration(shielding application: Application) -> ShieldConfiguration { return ShieldConfiguration( backgroundBlurStyle: UIBlurEffect.Style.systemThickMaterial, backgroundColor: UIColor.white, icon: UIImage(systemName: "stopwatch"), title: ShieldConfiguration.Label(text: "You are in a Present Session", color: .yellow) ) } override func configuration(shielding application: Application, in category: ActivityCategory) -> ShieldConfiguration { return ShieldConfiguration( backgroundBlurStyle: UIBlurEffect.Style.systemThickMaterial, backgroundColor: UIColor.white, icon: UIImage(systemName: "stopwatch"), title: ShieldConfiguration.Label(text: "You are in a Present Session", color: .yellow) ) } override func configuration(shielding webDomain: WebDomain) -> ShieldConfiguration { return ShieldConfiguration( backgroundBlurStyle: UIBlurEffect.Style.systemThickMaterial, backgroundColor: UIColor.white, icon: UIImage(systemName: "stopwatch"), title: ShieldConfiguration.Label(text: "You are in a Present Session", color: .yellow) ) } override func configuration(shielding webDomain: WebDomain, in category: ActivityCategory) -> ShieldConfiguration { return ShieldConfiguration( backgroundBlurStyle: UIBlurEffect.Style.systemThickMaterial, backgroundColor: UIColor.white, icon: UIImage(systemName: "stopwatch"), title: ShieldConfiguration.Label(text: "You are in a Present Session", color: .yellow) ) } } What am I missing?
5
2
2.6k
Jun ’25