Search code examples
iosswiftswift3eventkitekevent

Create Calendar, no local source even with iCloud off


I am trying to create a Calendar, not a calendar event but a Calendar. I can't get a local source and my app crashes.

Here is my code:

let newCalendar = EKCalendar(for: .event, eventStore: eventStore)

newCalendar.title = "Some Calendar Name"

let sourcesInEventStore = eventStore.sources

newCalendar.source = sourcesInEventStore.filter{
            (source: EKSource) -> Bool in
            source.sourceType.rawValue == EKSourceType.local.rawValue
            }.first!

I have my iCloud completely turned off and still can't get a local source.

I'm also trying to get this to work with iCloud turned on, I came up with this code, but it does not work

for let source in eventStore.sources
        {
            if(source.sourceType == EKSourceType.calDAV && source.title == "iCloud")
            {
                newCalendar.source = source
            }
        }

        if(newCalendar.source == nil)
        {
            for let source2 in eventStore.sources
            {
                if(source2.sourceType == EKSourceType.local)
                {
                    newCalendar.source = source2
                }
            }
        }

Solution

  • A few issues:

    Your code is crashing because you're force-unwrapping first from an array that is empty. Here are a few suggestions to make sure that the array of EKSource objects returns a non-empty array.

    First, ask the user for access to their calendar using requestAccess(to:) on an EKEventStore instance. Secondly, use an if let to unwrap a potentially optional value from your filtered array:

    let eventStore = EKEventStore()
    
    eventStore.requestAccess(to: .event) { (granted, error) in
        if granted {
            let newCalendar = EKCalendar(for: .event, eventStore: eventStore)
    
            newCalendar.title = "Some Calendar Name"
    
            let sourcesInEventStore = eventStore.sources
    
            let filteredSources = sourcesInEventStore.filter { $0.sourceType == .local }
    
            if let localSource = filteredSources.first {
                newCalendar.source = localSource
            } else {
                // Somehow, the local calendar was not found, handle error accordingly
            }
    
        } else {
            // check error and alert the user
        }
    }