1

I'm adopting SwiftUI for one of my previous apps, and at some point I need to add an event to the iOS calendar. Doing some researches on both the Apple Developer Forums and Stack Overflow, I came up with the following solution, that makes use of the UIViewControllerRepresentable protocol in order to still be able to use UIViewControllers with SwiftUI (you can find below the links to the discussions, for your reference).

Discussion on the Apple Dev Forums: https://forums.developer.apple.com/thread/120372

Discussion on Stack Overflow: SwiftUI: Send email

I'm almost there, but what I'm missing now it's the control of the authorization status to access the device calendar, and to trigger the request for such authorization in case it's required.

In Swift this would be the function to invoke to trigger the request, but I'm not sure how to handle this in my EKEventWrapper.

func requestAccess(to entityType: EKEntityType, 
        completion: @escaping EKEventStoreRequestAccessCompletionHandler)

Any ideas?

Thanks a lot!

My solution up to this point:

import Foundation
import SwiftUI
import EventKitUI

let eventStore = EKEventStore()

struct EKEventWrapper: UIViewControllerRepresentable {

    typealias UIViewControllerType = EKEventEditViewController

    @Binding var isShowing: Bool

    var theEvent = EKEvent.init(eventStore: eventStore)

    func makeUIViewController(context: UIViewControllerRepresentableContext<EKEventWrapper>) -> EKEventEditViewController {

        let calendar = EKCalendar.init(for: .event, eventStore: eventStore)

        theEvent.startDate = Date()
        theEvent.endDate = Date()
        theEvent.title = "Meeting"
        theEvent.calendar = calendar

        let controller = EKEventEditViewController()
        controller.event = theEvent
        controller.eventStore = eventStore
        controller.editViewDelegate = context.coordinator

        return controller
    }

    func updateUIViewController(_ uiViewController: EKEventWrapper.UIViewControllerType, context: UIViewControllerRepresentableContext<EKEventWrapper>) {
        //
    }


    func makeCoordinator() -> Coordinator {
        return Coordinator(isShowing: $isShowing)
    }

    class Coordinator : NSObject, UINavigationControllerDelegate, EKEventEditViewDelegate {

        @Binding var isShowing: Bool

        init(isShowing: Binding<Bool>) {
            _isShowing = isShowing
        }

        func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
            switch action {
            case .canceled:
                print("Canceled")
                isShowing = false                
            case .saved:
                print("Saved")
                do {
                    try controller.eventStore.save(controller.event!, span: .thisEvent, commit: true)
                }
                catch {
                    print("Problem saving event")
                }
                isShowing = false
            case .deleted:
                print("Deleted")
                isShowing = false
            @unknown default:
                print("I shouldn't be here")
                isShowing = false
            }
        }
    }
}
Salva
  • 707
  • 2
  • 9
  • 18

1 Answers1

1

I believe the below will do this, I have tested it in SwiftUI using a button to action the function. First post ever so apologies If I am totally off the mark!

import SwiftUI
import EventKit
import EventKitUI

struct calaccess: View {

var eventstore = EKEventStore()

var body: some View {

 func accesscalender(CalAccess: EKEventStore) {

    let eventstore = EKEventStore()

    eventstore.requestAccess(to: EKEntityType.event,completion:
               {(granted, error) in
            if !granted {
                print("Access to store not granted")
            }
    }),,,,
JimboS
  • 11
  • 1