startMonitoring is not working in iOS 17 and its extension methods also are not being called intervalDidStart(for activity: DeviceActivityName), it is working fine in iOS 16. Sometimes it freezes the app for a while and sometime throws the errors like:-
"This application is monitoring excessive activities"
and
System error occurred: related decl 'e' for USError(_nsError: Error Domain=UsageTrackingErrorDomain Code=101 "Failed to fetch a usage budget" UserInfo={NSLocalizedDescription=Failed to fetch a usage budget, NSLocalizedRecoverySuggestion=See Console for additional details.})
import Foundation
import FamilyControls
import DeviceActivity
import ManagedSettings
import SwiftUI
final class LockManager{
let calendar = Calendar.current
let appsModel = AppSelection()
let deviceActivityCenter = DeviceActivityCenter()
static let shared = LockManager()
private init(){}
func authorize(){
Task{
try? await AuthorizationCenter.shared.requestAuthorization(for: .individual)
}
}
func activateOneOffLockSession(for duration: Duration, group: AppGroup, mode: AccountabilityMode, completion: @escaping(_ error: Error?) -> Void){
authorize()
guard let hours = duration.hours, let minutes = duration.minutes else {return}
let id = UUID().uuidString
let schedule = DeviceActivitySchedule(
intervalStart: calendar.dateComponents([.calendar, .hour, .minute, .second], from: Date()),
intervalEnd: calendar.dateComponents([.calendar, .hour, .minute, .second], from: Date().addingTimeInterval(TimeInterval(hours*3600 + minutes*60))),
repeats: false
)
do {
try deviceActivityCenter.startMonitoring(.init(id), during: schedule)
if var lockSessions = UserDefaults.getLockSessions(){
lockSessions.oneOffSessions.append(.init(id: id, startTime: Date(), timeInterval: TimeInterval(hours*3600 + minutes*60), mode: mode, group: group))
UserDefaults.storeLockSessions(lockSessions: lockSessions)
}
else{
UserDefaults.storeLockSessions(lockSessions: .init(oneOffSessions: [.init(id: id, startTime: Date(), timeInterval: TimeInterval(hours*3600 + minutes*60), mode: mode, group: group)], scheduledSessions: []))
}
completion(nil)
} catch let error {
completion(error)
}
}
func scheduleLock(for lockSession: ScheduleLockSession, completion: @escaping(_ error: Error?) -> Void){
authorize()
let startTimeComponents = calendar.dateComponents([.hour, .minute], from: lockSession.startTime)
let endTimeComponents = calendar.dateComponents([.hour, .minute], from: lockSession.endTime)
stopScheduledLockSession(for: lockSession.id)
for (index, daysIndex) in lockSession.daysIndex.enumerated() {
let schedule = DeviceActivitySchedule(
intervalStart: DateComponents(calendar: .current, hour: startTimeComponents.hour, minute: startTimeComponents.minute, weekday: daysIndex+1),
intervalEnd: DateComponents(calendar: .current, hour: endTimeComponents.hour, minute: endTimeComponents.minute, weekday: daysIndex+1),
repeats: true
)
do {
try deviceActivityCenter.startMonitoring(.init("\(lockSession.id)\(index)"), during: schedule)
if index == lockSession.daysIndex.count-1{
if var lockSessions = UserDefaults.getLockSessions(){
if let index = lockSessions.scheduledSessions.firstIndex(where: {$0.id == lockSession.id}){
lockSessions.scheduledSessions[index] = lockSession
UserDefaults.storeLockSessions(lockSessions: lockSessions)
}
else{
lockSessions.scheduledSessions.append(lockSession)
UserDefaults.storeLockSessions(lockSessions: lockSessions)
}
}
else{
UserDefaults.storeLockSessions(lockSessions: .init(oneOffSessions: [], scheduledSessions: [lockSession]))
}
}
completion(nil)
} catch let error {
completion(error)
}
}
}
func removeOneOffLockSession(for id: String){
deviceActivityCenter.stopMonitoring([.init(id)])
ManagedSettingsStore.init(named: .init(id)).clearAllSettings()
if var lockSessions = UserDefaults.getLockSessions(){
lockSessions.oneOffSessions.removeAll(where: {$0.id == id})
UserDefaults.storeLockSessions(lockSessions: lockSessions)
}
}
func removeScheduledLockSession(for id: String){
stopScheduledLockSession(for: id)
if var lockSessions = UserDefaults.getLockSessions(){
lockSessions.scheduledSessions.removeAll(where: {$0.id == id})
UserDefaults.storeLockSessions(lockSessions: lockSessions)
}
}
func stopScheduledLockSession(for id: String){
deviceActivityCenter.stopMonitoring(
[.init("\(id)\(0)"),
.init("\(id)\(1)"),
.init("\(id)\(2)"),
.init("\(id)\(3)"),
.init("\(id)\(4)"),
.init("\(id)\(5)"),
.init("\(id)\(6)")])
}
}
class AppSelection: ObservableObject {
@Published var selectedApps = FamilyActivitySelection()
}
Tried every possible way but not worked for iOS 17