[英]How to identify an EKCalendar to store a user calendar selection
When working with the users calendar, I implemented an EKCalendarChooser which allows the user to select multiple of his calendars.在使用用户日历时,我实现了一个 EKCalendarChooser,它允许用户选择多个他的日历。 The selected calendar instances are retrieved just fine.所选的日历实例检索得很好。 Now I later want to use this selection but how can I store it permanently?现在我以后想使用此选择,但如何永久存储它?
My first approach was to use the calendars identifier and store them as a string array to UserDefaults like我的第一种方法是使用日历标识符并将它们作为字符串数组存储到 UserDefaults 中,例如
@State private var calendarSelection: [EKCalendar]
// my approach to convert the calendar selection into a storable format (string array of ids)
var selectedIds = [String]()
for calendar in calendarSelection {
selectedIds.append(calendar.calendarIdentifier)
}
// now store the string-array, eg. to user defaults:
UserDefaults.standard.set(selectedIds, forKey: "cids")
Unfortunately this doesn't work, because the calendarIdentifier
is not a permanent identifier and thus does change over time.不幸的是,这不起作用,因为calendarIdentifier
不是永久标识符,因此会随着时间而改变。 As apple states in their documentation:正如苹果在其文档中所述:
A full sync with the calendar will lose this identifier.与日历完全同步将丢失此标识符。 You should have a plan for dealing with a calendar whose identifier is no longer fetch-able by caching its other properties.您应该制定一个计划来处理一个日历,该日历的标识符不再能够通过缓存其他属性来获取。
How can the user's selection of his calendars be stored then?那么如何存储用户对其日历的选择呢?
Ok, this works for me now.好的,这现在对我有用。
I store the calendar identifier ...我存储日历标识符...
func calendarChooserDidFinish(_ calendarChooser: EKCalendarChooser) {
...
// store selected calendar identifier
selectedCalendar = calendarChooser.selectedCalendars.first?.calendarIdentifier
...
}
... then restore it. ...然后恢复它。
func showCalendarChooser() {
...
// check if calendar identifier still exists
if let selectedCalendarIdentifier = eventStore.calendar(withIdentifier: selectedCalendar) {
//select stored calendar
calendarChooser.selectedCalendars = [selectedCalendarIdentifier]
}
...
}
This is for 1 selected calendar only ( selectionStyle: .single
).这仅适用于 1 个选定的日历( selectionStyle: .single
)。
Changing this code to multiple calendars should be trivial.将此代码更改为多个日历应该很简单。
I also tested if the calendar identifier might change ... no joy so far.我还测试了日历标识符是否可能会改变......到目前为止还没有快乐。 It remained unchanged during all the tests.在所有测试中它保持不变。 If it should change ( nil
), no calendar will be selected and the app won't crash.如果它应该更改( nil
),则不会选择日历并且应用程序不会崩溃。
HTH HTH
I too have the same problem.我也有同样的问题。 The bad thing is you cannot tell when the identifier will change.不好的是,您无法判断标识符何时会更改。 Here is my work around...这是我的工作...
I store calendar identifier, calendar title, calendar source in userDefaults我将日历标识符、日历标题、日历源存储在 userDefaults 中
I fetch a set of calendar by comparing identifier first.我首先通过比较标识符来获取一组日历。 If identifier is not present in eventStore, then comparing the title AND source.如果 eventStore 中不存在标识符,则比较标题和来源。
Of course, you can add more properties but title + source should be enough in my opinion.当然,您可以添加更多属性,但我认为标题 + 来源应该足够了。
I have another part in my code that update new identifier in userDefaults.我的代码中有另一部分更新 userDefaults 中的新标识符。
if userSettings.selectedCalID != [] { //check if the array is empty or not. if userSettings.selectedCalID != [] { //检查数组是否为空。 If empty then do not use pre-selected calendar.如果为空,则不要使用预先选择的日历。
var selectedCalendarIdentifier : [EKCalendar] = [] for i in userSettings.selectedCalID{ print(i) if let eventStoreID = eventStore.calendar(withIdentifier: i){ selectedCalendarIdentifier.append(eventStoreID) } else { //This is part where calendar identifier has changed or not present in eventstore. Retrive new identifier by checking calendar title AND calendar source. if userSettings.selectedCalTitle != [] && userSettings.selectedCalSource != [] { let calTitle = userSettings.selectedCalTitle[userSettings.selectedCalID.firstIndex(of: i) ?? 0] let calSource = userSettings.selectedCalSource[userSettings.selectedCalID.firstIndex(of: i) ?? 0] print("\\(calTitle) - \\(calSource)") if let eventStoreCalNewID = eventStore.calendars(for: .event).filter({($0.title == calTitle) && ($0.source.title == calSource)}).first?.calendarIdentifier{ if let eventStoreID = eventStore.calendar(withIdentifier: eventStoreCalNewID){ selectedCalendarIdentifier.append(eventStoreID) } } } } } chooser.selectedCalendars = Set(selectedCalendarIdentifier) }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.