如何使用 swift 在设备日历中添加事件?
How to add an event in the device calendar using swift?
我想知道如何在设备中添加日历事件,但使用 swift。我知道 Objective-C 中有一些示例,但目前 swift 中没有任何示例。非常感谢。
注意:如果您的应用因 This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSCalendarsUsageDescription key with a string value explaining to the user how the app uses this data.
而崩溃,您需要将 NSCalendarsUsageDescription
添加到 info.plist。可以仿照例子.
Swift 5.0 版本
import Foundation
import EventKit
let eventStore : EKEventStore = EKEventStore()
// 'EKEntityTypeReminder' or 'EKEntityTypeEvent'
eventStore.requestAccess(to: .event) { (granted, error) in
if (granted) && (error == nil) {
print("granted \(granted)")
print("error \(error)")
let event:EKEvent = EKEvent(eventStore: eventStore)
event.title = "Test Title"
event.startDate = Date()
event.endDate = Date()
event.notes = "This is a note"
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let error as NSError {
print("failed to save event with error : \(error)")
}
print("Saved Event")
}
else{
print("failed to save event with error : \(error) or access not granted")
}
}
参考:https://gist.github.com/mchirico/d072c4e38bda61040f91
我能够对此进行调整并消除上述答案(以及其他一些)的评论中提到的编译器错误,如下所示:
var eventStore : EKEventStore = EKEventStore()
// 'EKEntityTypeReminder' or 'EKEntityTypeEvent'
eventStore.requestAccessToEntityType(EKEntityType.Event, completion: {
(granted, error) in
if (granted) && (error == nil) {
print("granted \(granted)")
print("error \(error)")
var event:EKEvent = EKEvent(eventStore: eventStore)
event.title = "Test Title"
event.startDate = NSDate()
event.endDate = NSDate()
event.notes = "This is a note"
event.calendar = eventStore.defaultCalendarForNewEvents
eventStore.saveEvent(event, span: EKSpan.ThisEvent, error: nil)
print("Saved Event")
}
})
但是,我仍然在底部收到关于 "EKSpan.ThisEvent" 的以下错误:调用中的参数标签不正确(有':span:error:',预期为' :跨度:提交:')。
我尝试将 "error" 更改为 "commit," 但它给了我一个编译器错误,说它需要一个 Bool 而不是 nil。这似乎是一个与 swift 语法更新有关的问题。
编辑:我最终关注了 this tutorial 并且能够让它发挥作用。
首先,请求访问日历的权限,并且(如果授予该权限)调用一个函数来添加事件。
var savedEventId : String = ""
func requestAccessPermission() {
let eventStore = EKEventStore()
let startDate = NSDate()
let endDate = startDate.dateByAddingTimeInterval(60 * 60) // Ends one hour later
if (EKEventStore.authorizationStatusForEntityType(.Event) != EKAuthorizationStatus.Authorized) {
eventStore.requestAccessToEntityType(.Event, completion: {
granted, error in
self.createEvent(eventStore, title: "Test Title", startDate: startDate, endDate: endDate)
})
} else {
createEvent(eventStore, title: "Test Title", startDate: startDate, endDate: endDate)
}
}
上面代码片段中调用的添加事件的函数:
func createEvent(eventStore: EKEventStore, title: String, startDate: NSDate, endDate: NSDate) {
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.saveEvent(event, span: .ThisEvent)
savedEventId = event.eventIdentifier
} catch {
print("Error Saving")
}
}
Swift 3.0 兼容:
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.notes = description
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let e as NSError {
completion?(false, e)
return
}
completion?(true, nil)
} else {
completion?(false, error as NSError?)
}
})
}
同时导入EventKit
因此您可以从任何地方轻松调用此方法:
addEventToCalendar(title: "Girlfriend birthday", description: "Remember or die!", startDate: NSDate(), endDate: NSDate())
如果您愿意,可以将此方法放在一个实用程序 class 中并将其定义为 'static'。
您需要将 "Privacy - Calendars Usage Description" 添加到 info.plist。
以下代码适用于最新版本的 xcode 和 swift 3.
import EventKit
class EventHelper
{
let appleEventStore = EKEventStore()
var calendars: [EKCalendar]?
func generateEvent() {
let status = EKEventStore.authorizationStatus(for: EKEntityType.event)
switch (status)
{
case EKAuthorizationStatus.notDetermined:
// This happens on first-run
requestAccessToCalendar()
case EKAuthorizationStatus.authorized:
// User has access
print("User has access to calendar")
self.addAppleEvents()
case EKAuthorizationStatus.restricted, EKAuthorizationStatus.denied:
// We need to help them give us permission
noPermission()
}
}
func noPermission()
{
print("User has to change settings...goto settings to view access")
}
func requestAccessToCalendar() {
appleEventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
DispatchQueue.main.async {
print("User has access to calendar")
self.addAppleEvents()
}
} else {
DispatchQueue.main.async{
self.noPermission()
}
}
})
}
func addAppleEvents()
{
let event:EKEvent = EKEvent(eventStore: appleEventStore)
event.title = "Test Event"
event.startDate = NSDate() as Date
event.endDate = NSDate() as Date
event.notes = "This is a note"
event.calendar = appleEventStore.defaultCalendarForNewEvents
do {
try appleEventStore.save(event, span: .thisEvent)
print("events added with dates:")
} catch let e as NSError {
print(e.description)
return
}
print("Saved Event")
}
}
这在 iOS 11.2 Xcode 9.2 上真的很慢,所以我修改了 Luca Davanzo 的答案以使用队列(工作得更快):
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
DispatchQueue.global(qos: .background).async { () -> Void in
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.notes = description
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let e as NSError {
completion?(false, e)
return
}
completion?(true, nil)
} else {
completion?(false, error as NSError?)
}
})
}
}
与位置和警报相同
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, location: String?, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
DispatchQueue.global(qos: .background).async { () -> Void in
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
let alarm = EKAlarm(relativeOffset: -3600.0)
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.notes = description
event.alarms = [alarm]
event.location = location
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let e as NSError {
completion?(false, e)
print ("\(#file) - \(#function) error: \(e.localizedDescription)")
return
}
completion?(true, nil)
} else {
completion?(false, error as NSError?)
print ("\(#file) - \(#function) error: \(error)")
}
})
}
}
我想知道如何在设备中添加日历事件,但使用 swift。我知道 Objective-C 中有一些示例,但目前 swift 中没有任何示例。非常感谢。
注意:如果您的应用因 This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSCalendarsUsageDescription key with a string value explaining to the user how the app uses this data.
而崩溃,您需要将 NSCalendarsUsageDescription
添加到 info.plist。可以仿照例子
Swift 5.0 版本
import Foundation
import EventKit
let eventStore : EKEventStore = EKEventStore()
// 'EKEntityTypeReminder' or 'EKEntityTypeEvent'
eventStore.requestAccess(to: .event) { (granted, error) in
if (granted) && (error == nil) {
print("granted \(granted)")
print("error \(error)")
let event:EKEvent = EKEvent(eventStore: eventStore)
event.title = "Test Title"
event.startDate = Date()
event.endDate = Date()
event.notes = "This is a note"
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let error as NSError {
print("failed to save event with error : \(error)")
}
print("Saved Event")
}
else{
print("failed to save event with error : \(error) or access not granted")
}
}
参考:https://gist.github.com/mchirico/d072c4e38bda61040f91
我能够对此进行调整并消除上述答案(以及其他一些)的评论中提到的编译器错误,如下所示:
var eventStore : EKEventStore = EKEventStore()
// 'EKEntityTypeReminder' or 'EKEntityTypeEvent'
eventStore.requestAccessToEntityType(EKEntityType.Event, completion: {
(granted, error) in
if (granted) && (error == nil) {
print("granted \(granted)")
print("error \(error)")
var event:EKEvent = EKEvent(eventStore: eventStore)
event.title = "Test Title"
event.startDate = NSDate()
event.endDate = NSDate()
event.notes = "This is a note"
event.calendar = eventStore.defaultCalendarForNewEvents
eventStore.saveEvent(event, span: EKSpan.ThisEvent, error: nil)
print("Saved Event")
}
})
但是,我仍然在底部收到关于 "EKSpan.ThisEvent" 的以下错误:调用中的参数标签不正确(有':span:error:',预期为' :跨度:提交:')。
我尝试将 "error" 更改为 "commit," 但它给了我一个编译器错误,说它需要一个 Bool 而不是 nil。这似乎是一个与 swift 语法更新有关的问题。
编辑:我最终关注了 this tutorial 并且能够让它发挥作用。
首先,请求访问日历的权限,并且(如果授予该权限)调用一个函数来添加事件。
var savedEventId : String = "" func requestAccessPermission() { let eventStore = EKEventStore() let startDate = NSDate() let endDate = startDate.dateByAddingTimeInterval(60 * 60) // Ends one hour later if (EKEventStore.authorizationStatusForEntityType(.Event) != EKAuthorizationStatus.Authorized) { eventStore.requestAccessToEntityType(.Event, completion: { granted, error in self.createEvent(eventStore, title: "Test Title", startDate: startDate, endDate: endDate) }) } else { createEvent(eventStore, title: "Test Title", startDate: startDate, endDate: endDate) } }
上面代码片段中调用的添加事件的函数:
func createEvent(eventStore: EKEventStore, title: String, startDate: NSDate, endDate: NSDate) { let event = EKEvent(eventStore: eventStore) event.title = title event.startDate = startDate event.endDate = endDate event.calendar = eventStore.defaultCalendarForNewEvents do { try eventStore.saveEvent(event, span: .ThisEvent) savedEventId = event.eventIdentifier } catch { print("Error Saving") } }
Swift 3.0 兼容:
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.notes = description
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let e as NSError {
completion?(false, e)
return
}
completion?(true, nil)
} else {
completion?(false, error as NSError?)
}
})
}
同时导入EventKit
因此您可以从任何地方轻松调用此方法:
addEventToCalendar(title: "Girlfriend birthday", description: "Remember or die!", startDate: NSDate(), endDate: NSDate())
如果您愿意,可以将此方法放在一个实用程序 class 中并将其定义为 'static'。
您需要将 "Privacy - Calendars Usage Description" 添加到 info.plist。 以下代码适用于最新版本的 xcode 和 swift 3.
import EventKit
class EventHelper
{
let appleEventStore = EKEventStore()
var calendars: [EKCalendar]?
func generateEvent() {
let status = EKEventStore.authorizationStatus(for: EKEntityType.event)
switch (status)
{
case EKAuthorizationStatus.notDetermined:
// This happens on first-run
requestAccessToCalendar()
case EKAuthorizationStatus.authorized:
// User has access
print("User has access to calendar")
self.addAppleEvents()
case EKAuthorizationStatus.restricted, EKAuthorizationStatus.denied:
// We need to help them give us permission
noPermission()
}
}
func noPermission()
{
print("User has to change settings...goto settings to view access")
}
func requestAccessToCalendar() {
appleEventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
DispatchQueue.main.async {
print("User has access to calendar")
self.addAppleEvents()
}
} else {
DispatchQueue.main.async{
self.noPermission()
}
}
})
}
func addAppleEvents()
{
let event:EKEvent = EKEvent(eventStore: appleEventStore)
event.title = "Test Event"
event.startDate = NSDate() as Date
event.endDate = NSDate() as Date
event.notes = "This is a note"
event.calendar = appleEventStore.defaultCalendarForNewEvents
do {
try appleEventStore.save(event, span: .thisEvent)
print("events added with dates:")
} catch let e as NSError {
print(e.description)
return
}
print("Saved Event")
}
}
这在 iOS 11.2 Xcode 9.2 上真的很慢,所以我修改了 Luca Davanzo 的答案以使用队列(工作得更快):
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
DispatchQueue.global(qos: .background).async { () -> Void in
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.notes = description
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let e as NSError {
completion?(false, e)
return
}
completion?(true, nil)
} else {
completion?(false, error as NSError?)
}
})
}
}
与位置和警报相同
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, location: String?, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
DispatchQueue.global(qos: .background).async { () -> Void in
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
let alarm = EKAlarm(relativeOffset: -3600.0)
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.notes = description
event.alarms = [alarm]
event.location = location
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let e as NSError {
completion?(false, e)
print ("\(#file) - \(#function) error: \(e.localizedDescription)")
return
}
completion?(true, nil)
} else {
completion?(false, error as NSError?)
print ("\(#file) - \(#function) error: \(error)")
}
})
}
}