I am using Swift 4.1. And I want to write a function which will collect all events from all calendars in Calendar app of iOS. Thanks to this answer on stackoverflow: How to get all Events out of a Calendar (Swift) I was able to write my own class
and call it Cale
. Please, look at this:
import UIKit
import EventKit
class Cale {
private func createDate(year: Int) -> Date {
var components = DateComponents()
components.year = year
components.timeZone = TimeZone(secondsFromGMT: 0)
return Calendar.current.date(from: components)!
}
private let eventStore = EKEventStore()
private func get() {
let calendars = eventStore.calendars(for: .event)
for calendar in calendars {
// This checking will remove Birthdays and Hollidays callendars
guard calendar.allowsContentModifications else {
continue
}
let start = createDate(year: 2016)
let end = createDate(year: 2025)
print("start: \(start)")
print(" end: \(end)")
let predicate = eventStore.predicateForEvents(withStart: start, end: end, calendars: [calendar])
print("predicate: \(predicate)")
let events = eventStore.events(matching: predicate)
for event in events {
print(" title: \(event.title!)")
print("startDate: \(event.startDate!)")
print(" endDate: \(event.endDate!)")
}
}
}
func checkStatusAndGetAllEvents() {
let currentStatus = EKEventStore.authorizationStatus(for: EKEntityType.event)
switch currentStatus {
case .authorized:
//print("authorized")
self.get()
case .notDetermined:
//print("notDetermined")
eventStore.requestAccess(to: .event) { accessGranted, error in
if accessGranted {
self.get()
} else {
print("Change Settings to Allow Access")
}
}
case .restricted:
print("restricted")
case .denied:
print("denied")
}
}
}
Quite simple class, you can use it, it is working but with one exception.
The main function there is get()
In this function I am creating predicate based on two dates: start and end. As you can see start date is:
2016-01-01 00:00:00 +0000
and end date is:
2025-01-01 00:00:00 +0000
But if we run the program we will see that predicate will be like this:
CADEventPredicate start:01/01/2016, 03:00; end:01/01/2020, 03:00; cals:( 2 )
Only from 2016 to 2020, 4 years! I have tested it on different dates, but I could get predicate with 4 years interval maximum. It means, it will not give me all events! So question is: How to get all events from calendar? If it possible, without using dates!
Thank you for any future help or advice!
After spending so much time, i got a solution to my problem. My problem was as below,
event start date 2019-03-15 09:00:00 +0000
event end date 2019-03-15 14:00:00 +0000
the predicate as below,
CADEventPredicate start:15/03/19, 1:30 PM; end:15/03/19, 7:30 PM; cals:(null)
As i am from India, the predicate is adding GMT+5:30 to my actual event start and end time. I got a method from stack overflow, to convert to local & global timezone as below.
extension Date {
// Convert local time to UTC (or GMT)
func toGlobalTime() -> Date {
let timezone = TimeZone.current
let seconds = -TimeInterval(timezone.secondsFromGMT(for: self))
return Date(timeInterval: seconds, since: self)
}
// Convert UTC (or GMT) to local time
func toLocalTime() -> Date {
let timezone = TimeZone.current
let seconds = TimeInterval(timezone.secondsFromGMT(for: self))
return Date(timeInterval: seconds, since: self)
}
}
While passing start and end date with time to predicate i am converting to globalTimeZone as below.
let predicate = eventStore.predicateForEvents(withStart: eventStartDateTime.toGlobalTime(), end: eventEndDateTime.toGlobalTime(), calendars: nil)
If you don't have time, you have only start & end dates, then use predicate as below,
event start date 2019-03-15 00:00:00 +0000
event end date 2019-03-15 00:00:00 +0000
let predicate = eventStore.predicateForEvents(withStart: eventStartDateTime, end: eventEndDateTime, calendars: nil)
Because if you don't have time and converting to globalTimeZone, you may face issues in deleting the events.
I hope it will help some one.
来源:https://stackoverflow.com/questions/51439574/swift-4-how-to-get-all-events-from-calendar