PermissionsKit: New iOS 17 requestFullAccessToEvents returns always notDetermined on first run

New iOS 17 requestFullAccessToEvents returns always notDetermined on first run of an app.

@ivanvorobei @alexanderpuchta is it working to you?

We need a fix there https://github.com/sparrowcode/PermissionsKit/pull/325 but we need to have a return value in func request(completion: @escaping () -> Void) because requestFullAccessToEvents returns accessGranted = true but status or EKEventStore.authorizationStatus(for: EKEntityType.event) returns .notDetermined until you run your app again.

So this library still doesn’t work well on iOS 17.

About this issue

  • Original URL
  • State: closed
  • Created 9 months ago
  • Comments: 15 (15 by maintainers)

Most upvoted comments

Yes, it looks really promising! Thanks for the effort, Alex.

@ivanvorobei @ostatnicky to fix the issue with initial result is always .notDetermined we could add an @available(iOS 17.0, *) func request() async -> Status to class Permission.

this could look like this:

   
    @available(iOS 17.0, *)
    public override func request() async -> Status {
        
        let eventStore = EKEventStore()
        
        return await withCheckedContinuation { continuation in
            switch kind {
            case .calendar(let access):
                switch access {
                case .full:
                    eventStore.requestFullAccess { (isGranted: Bool, error: Error?) in
                        continuation.resume(returning: isGranted ? .authorized : .denied)
                    }
                    
                case .write:
                    eventStore.requestWriteOnlyAccess { (isGranted: Bool, error: Error?) in
                        continuation.resume(returning: isGranted ? .authorized : .denied)
                    }
                }
                
            default:
                continuation.resume(returning: .notDetermined)
            }
        }
    }

this could then be used within apps like:

let status = await Permission.calendar(access: .full).request()

helper methods for EKEventStore can clean up code, so you don’t have to write those requestFullAccess or requestWriteOnlyAccess again and again.

private extension EKEventStore {
    
    typealias EventStoreAction = ((isGranted: Bool, error: Error?)) -> Void
    
    func requestFullAccess(completion: @escaping EventStoreAction) {
        if #available(iOS 17.0, *) {
            self.requestFullAccessToEvents { (accessGranted: Bool, error: Error?) in
                DispatchQueue.main.async {
                    completion((isGranted: accessGranted, error: error))
                }
            }
        } else {
            self.requestAccess(to: EKEntityType.event) { (accessGranted: Bool, error: Error?) in
                DispatchQueue.main.async {
                    completion((isGranted: accessGranted, error: error))
                }
            }
        }
    }
    
    func requestWriteOnlyAccess(completion: @escaping EventStoreAction) {
        if #available(iOS 17.0, *) {
            self.requestWriteOnlyAccessToEvents { (accessGranted: Bool, error: Error?) in
                DispatchQueue.main.async {
                    completion((isGranted: accessGranted, error: error))
                }
            }
        }
    }
}

the default request(completion: @escpaing () ->Void)) could then be refactored like this:

    public override func request(completion: @escaping () -> Void) {
        
        let eventStore = EKEventStore()
        
        if #available(iOS 17.0, *) {
            switch kind {
            case .calendar(let access):
                switch access {
                case .full:
                    eventStore.requestFullAccess { (isGranted: Bool, error: Error?) in
                        completion()
                    }
                    
                case .write:
                    eventStore.requestWriteOnlyAccess { (isGranted: Bool, error: Error?) in
                        completion()
                    }
                }
                
            default:
                completion()
            }
        } else {
            eventStore.requestFullAccess { (isGranted: Bool, error: Error?) in
                completion()
            }
        }
    }