【发布时间】:2018-06-10 22:19:29
【问题描述】:
我正在尝试将所有日历中的特定事件复制到目标日历。不幸的是,我的活动没有保存在目标日历中。
分步简化我的代码:
- 检查权限(成功)
- 加载日历(成功)
- 加载事件(成功)
- 保存事件(失败)
我确定有一些事件要从终端保存,该终端会打印几次“尝试保存”。
看起来代码通过“try self.eventStore.save(event, span: .thisEvent)”并在那里退出函数而不调用“Saved”或进入catch子句。
有源代码:
import UIKit
import EventKit
class ViewController: UIViewController{
@IBOutlet weak var status: UILabel!
var calendars: [EKCalendar]?
var targetCalendar: EKCalendar?
var targetCalendarEvents: [EKEvent]?
let eventStore = EKEventStore()
let targetCalendarName = "TargetCalendarName"
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(_ animated: Bool) {
DispatchQueue.main.async{
self.status.text = "Idle"
}
checkCalendarAuthorizationStatus()
}
func checkCalendarAuthorizationStatus() {
let status = EKEventStore.authorizationStatus(for: EKEntityType.event)
switch (status) {
case EKAuthorizationStatus.notDetermined:
// This happens on first-run
requestAccessToCalendar()
case EKAuthorizationStatus.authorized:
// Things are in line with being able to show the calendars in the table view
loadCalendars()
loadEvents()
case EKAuthorizationStatus.restricted, EKAuthorizationStatus.denied:
// We need to help them give us permission
print("Missing permissions [00]")
}
}
func requestAccessToCalendar() {
eventStore.requestAccess(to: EKEntityType.event, completion: {
(accessGranted: Bool, error: Error?) in
if accessGranted == true {
DispatchQueue.main.async(execute: {
self.loadCalendars()
self.loadEvents()
})
} else {
print("Missing permissions [01]")
}
})
}
func loadEvents(){
print("Loading..")
DispatchQueue.main.async{
self.status.text = "Loading"
}
let eventStore = EKEventStore()
var initialized = false
//Two months
let dateTo = NSDate(timeIntervalSinceNow: +30*24*3600 * 2)
for calendar in self.calendars! {
let predicate = eventStore.predicateForEvents(withStart: Date() as Date as Date, end: dateTo as Date, calendars: [calendar])
let events = eventStore.events(matching: predicate)
if calendar.title == targetCalendarName {
print("Initialized")
targetCalendar = calendar
targetCalendarEvents = events
initialized = true
}
}
if(!initialized){
print("Not Initialized")
} else {
for calendar in self.calendars! {
let predicate = eventStore.predicateForEvents(withStart: Date() as Date as Date, end: dateTo as Date, calendars: [calendar])
let events = eventStore.events(matching: predicate)
if calendar.title != targetCalendarName && calendar.title != "Contacts" {
//print("Loaded Calendar \(calendar.title)")
print("Loaded Calendar")
for event in events {
if(!(event.location?.isEmpty)!){
//print("Event \(event.location ?? "Missing Location") \(event.startDate) \(event.endDate)")
addEventToTarget(eventToAdd: event)
}
}
}
}
}
DispatchQueue.main.async {
self.status.text = "Done"
}
print("Done")
}
func loadCalendars() {
self.calendars = eventStore.calendars(for: EKEntityType.event)
}
func addEventToTarget(eventToAdd: EKEvent){
eventStore.requestAccess(to: .event) { (granted, error) in
for event in self.targetCalendarEvents! {
if(!(event.location?.isEmpty)!){
if(
eventToAdd.title == event.title &&
eventToAdd.startDate == event.startDate &&
eventToAdd.endDate == event.endDate
){
print("Possible duplicate - skipping")
return
}
}
}
if (granted) && (error == nil) {
let event:EKEvent = EKEvent(eventStore: self.eventStore)
event.title = eventToAdd.title
event.startDate = eventToAdd.startDate
event.endDate = eventToAdd.endDate
event.notes = ""
event.location = eventToAdd.location
event.calendar = self.targetCalendar
//print("Trying to save \(event.title) \(String(describing: event.location))")
print("Trying to save")
do {
try self.eventStore.save(event, span: .thisEvent)
print("Saved \(event.title) \(String(describing: event.location)) in \(event.calendar.title)")
} catch {
print("failed to save event with error : \(error as NSError)")
}
}
else{
print("failed to save event with error : \(String(describing: error)) or access not granted")
}
}
}
}
TargetCalendarName 是正确的日历名称
有时有些事件可以成功保存,但只有几个 (2-5) 可以保存数百个事件。我不知道为什么。 所以 5 for 200 对我来说还不够。
【问题讨论】:
-
您向
eventStore.requestAccess(to: .event) {发出大量调用并保存在完成处理程序中。对完成处理程序的每一次调用都可以在不同的线程上返回,因此您遇到了线程混乱。你为什么做这个?预先检查访问一次,然后循环浏览要保存的内容并保存它们。 -
@matt 好点,会试试的
-
一般评论,不要使用
NSDate,只需使用Date,“Date() as Date as Date”可以简化为Date()。快速测试是可以的,但你不应该通过乘以秒来计算时间范围;夏令时的开始/结束将打破这一点