简体   繁体   English

如何识别 EKCalendar 以存储用户日历选择

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM