Post

Replies

Boosts

Views

Activity

Reply to Family Controls: `authorizationStatus` and `requestAuthorization` beyond dysfunctional
authorizationStatus is not updating on permission changed. Alternate: This is what I came up after spending hours in trying different solutions. You can simply add below requestAuthorization in applicationWillEnterForeground (if you have logged in mechanism please call when user logged in), this will initiate permission popover if permission required otherwise it will not do anything. Task { do { try await AuthorizationCenter.shared.requestAuthorization(for: .individual) } catch { print(error) } } And to observe the permission status AuthorizationCenter.shared.$authorizationStatus.sink { authorizationStatus in print("authorizationStatus updated") } .store(in: &cancellables) Though this observer will get called on every app launch, you can update your views or block apps again depending on your needs.
Jan ’25
Reply to Device Activity Report Per hour Screen-time of apps for Graph
After spending some time I been able to resolve by myself. Filters played it's part To fetch daily per hour screen-time data, we need to use this filter DeviceActivityFilter( segment: .hourly(during: Calendar.current.dateInterval(of: .day, for: .now)!), users: .all, devices: .init([.iPhone, .iPad]) ) Hourly segment will ensure that data DeviceActivityResults will have activitySegments on per hour basis and .day dateInterval will give whole day's data. Now you can configure your data models accordingly for example: func makeConfiguration(representing data: DeviceActivityResults<DeviceActivityData>) async -> ActivityReport { for await d in data { // activitySegments are per hour data because we have applied hourly filter for await a in d.activitySegments { // Here you can check the associated hour to the segment let hour = a.dateInterval.start for await c in a.categories { for await app in c.applications { // Now this app's data will be on the basis of per hour logger.log("Apps usage segment dateInterval: \(hour, privacy: .public)") } } } } }
Nov ’24
Reply to Device Activity Monitor
You can do something like this: Unlock app for certain period of time via ShieldActionExtension, during this unlock process save that app using it's Token in shared preference (Shared User Defaults). You can save using this procedure: struct ApplicationProfile: Codable, Hashable { let id: UUID let applicationToken: ApplicationToken init(id: UUID = UUID(), applicationToken: ApplicationToken) { self.applicationToken = applicationToken self.id = id } } // You can get this token from ShieldAction delegate method handle action let profile = ApplicationProfile(applicationToken: token) SharedData.addApplicationProfile(profile) The app you have unlocked is saved, now schedule an event according to your desired threshold using the profile you have in your shared cache. let unlockTime = 900 // Time in seconds let threshold = DateComponents(second: unlockTime) let event: [DeviceActivityEvent.Name: DeviceActivityEvent] = [ DeviceActivityEvent.Name(profile.id.uuidString): DeviceActivityEvent( applications: Set<ApplicationToken>([application]), threshold: threshold ) ] let center = DeviceActivityCenter() let schedule = DeviceActivitySchedule( intervalStart: DateComponents(hour: 0, minute: 0), intervalEnd: DateComponents(hour: 23, minute: 59), repeats: true ) do { try center.startMonitoring(DeviceActivityName(profile.id.uuidString), during: schedule, events: event) } catch { print("Device monitoring error: \(error)") } } This will schedule a device activity for 24 hours, which will monitor the app usage. Once that threshold reached (user have used app for 15 minutes in your case) your DeviceActivityMonitorExtension delegate method eventDidReachThreshold will get called Now lock the app again. override func eventDidReachThreshold(_ event: DeviceActivityEvent.Name, activity: DeviceActivityName) { super.eventDidReachThreshold(event, activity: activity) // Handle the event reaching its threshold. guard let activityId = UUID(uuidString: activity.rawValue) else { return } guard let application = SharedData.getApplicationProfile(id: activityId) else { return } store.shield.applications?.insert(application.applicationToken) SharedData.removeApplicationProfile(application) logger.log("DeviceActivityMonitorExtension: Apps shield set again") } In this way you will be able to apply shield on respective app after your threshold reached. Hope that helps you.
Nov ’24