EKCalendar中的“完整日历同步”具体包括什么?

20

EKCalendar类的文档针对calendarIdentifier属性说明如下:

与日历进行完整同步将会丢失此标识符。您应该有一个处理无法通过获取缓存其其他属性来获得标识符的日历的计划。

"完整同步"是在什么时候发生的?除了calendarIdentifier之外,哪些属性可能会发生变化?


在这里,您可以找到一些解释。http://oleb.net/blog/2012/05/creating-and-deleting-calendars-in-ios/ - Ilan
1
这是指将本地日历与CalDAV或iCloud日历同步。当发生这种情况时,无法再使用calendarWithIdentifier检索本地日历。因此,如果您缓存了calendarIdentifier,它将毫无用处。您应该访问iCloud日历,或者按照文档建议,缓存您以后要使用的日历属性的值。 - Hadi Brais
3个回答

5

何时会发生“完全同步”?
日历和提醒编程指南以以下方式解释了这个问题:

如果来自您的应用程序之外对日历数据库进行更改, Event Kit 可以通过通知检测到更改,以便您的应用程序可以 适当地采取行动。使用 Event Kit 对日历项目进行的更改将 自动同步到相关联的日历(CalDAV、Exchange 等)。

我在您的应用程序打开时看到了以下“完全同步”事件的场景:
1. 用户将您的应用程序发送到后台并打开日历应用程序。他更改了日历名称,添加/编辑/删除事件,甚至删除了一些日历。
2. 用户在 Mac 上对 iCloud 日历进行了一些更改。iOS 设备收到通知,因此必须进行同步。
3. 第三方应用程序接收到静默通知,iOS 在后台启动它,应用程序基于通知创建一些日历事件。

一般来说,“完全同步”事件可能随时发生。
如何检测和处理“完全同步”事件?《观察日历数据库的外部更改》这样解释:
另一个进程或应用程序在您的应用程序运行时可能会修改日历数据库。如果您的应用程序获取日历事件或提醒,则应注册以接收有关日历数据库更改的通知。通过这样做,您可以确保向用户显示的日历和提醒信息是最新的。
以下是注册此类通知的代码示例:
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(storeChanged:)
                                             name:EKEventStoreChangedNotification
                                           object:eventStore];

我认为有必要重新创建EKCalendar类的实例并在需要时重新缓存calendarIdentifier。除了calendarIdentifier,还有哪些属性可能会发生变化?我无法找到任何关于这个问题的文档。但是由于日历甚至可能在某个时刻不存在(例如用户在日历应用中手动删除它),因此在发生“完全同步”事件后,EKCalendar对象的任何属性都可能无效。此外,阅读上面的链接以获取更多信息和详细信息也是有意义的。

1
这个答案中的"When"部分是不正确的。正常的“同步”和“完全同步”之间有区别。例如,重命名日历或添加事件等操作不会触发完全同步,因此也不会导致calendarIdentifier更改。请参见VolenD的答案,了解如何触发完全同步的示例。 - jk7

3

当添加日历时,将进行完全同步。所有添加的日历都将被缓存到系统(iOS或MacOS)中,并接收唯一的ID。在MacOS上可以轻松检查 - 如果您转到目录〜/ Library / Calendars /,您将看到一个包含类似以下目录的列表:

3CC21C9A-0B3C-4A76-B2B0-8D3643CF2992.exchange/

45EF644F-672A-453A-ACC9-A565F017F766.calendar/

可以使用 calendarIdentifier 检查的唯一 ID 是什么。

为了测试在 iOS 上如何更改 calendarIdentifier,您可以在 iCloud 中创建一个名为 testcal 的日历,并使用以下代码获取标识符:

EKEventStore *eventStore = [[EKEventStore alloc] init];
NSArray *cal = [eventStore calendarsForEntityType:EKEntityTypeEvent];
for (EKCalendar *i in cal) {
    if([i.title isEqualToString:@"testcal"]) {
        NSLog(@"%@", i.calendarIdentifier);
    }
}

接下来,禁用日历(设置-> iCloud -> 日历,选择“从我的iPhone中删除”),然后启用它。当您再次执行代码时,您将看到一个不同的标识符,尽管日历是相同的。

另一种情况是当本地缓存损坏时,会执行完整同步。在这种情况下,日历应该尝试重建它。

因此,通过其标识符查找日历并不是一个好主意,您可以使用标题、类型、颜色等来唯一标识它。


这是导致 calendarIdentifier 改变并引起完全同步的正确答案。 - jk7

0
根据iTunes论坛,当完全同步未指定时,取决于它们。

http://www.openradar.appspot.com/15671424

https://idmsa.apple.com/IDMSWebAuth/login?appIdKey=4a75046cda87eab6386a9eae8caabb9824e328b9abc988119b39296495ec184c&path=/login.jspa#926856

与可能会发生变化的属性相关的是所有可以被其他线程访问的属性(与calendarIdentifier相同),因此是那些非原子性且可以更改的属性,以下是我找到的:

allowsContentModifications, CGColor, immutable,title,type,allowedEntityTypes,source,subscribed,supportedEventAvailabilities

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接