gpt4 book ai didi

iOS、CloudKit - 我的应用程序启动时是否需要进行提取?

转载 作者:可可西里 更新时间:2023-11-01 05:43:04 26 4
gpt4 key购买 nike

我正在为 iCloud 更改通知设置注册。

假设一个新设备被添加到 icloud 帐户,我只是想知道该设备将如何获取私有(private)数据库记录。

我需要进行一次性查询吗?

我希望通知将在所有其他时间使用。

最佳答案

让我们从订阅通知的一些相关特征开始:

首先:订阅通知特定于用户+设备对。如果我在手机上安装你的应用程序,我就会开始收到通知。在我也将应用程序安装到另一台设备上之前,我不会在另一台设备上收到通知。

第二: 通知不可靠。苹果文档很清楚,他们不保证交付。当您收到通知时,之前可能有多个通知。因此,Apple 提供了两种机制来跟踪您看到的通知:

  1. 已读/未读状态:您可以将通知标记为已读。 Apple 的文档在这方面的实际作用自相矛盾。 This page

If you mark one or more notifications as read using a CKMarkNotificationsReadOperation object, those notifications are not returned, even if you specify nil for previousServerChangeToken.

然而,事实并非如此。 fetch 操作清楚地返回已读和未读通知。 WWDC 2014 视频 231(Advanced Cloudkit)与文档页面相矛盾,解释说总是返回未读 token 以及已读 token ,因此多个设备可以同步。该视频提供了一个具体示例,展示了此行为的好处。此行为也记录在 SO 上:CKFetchNotificationChangesOperation returning old notifications

  1. 更改 token :每个提取操作都会返回一个您可以缓存的更改 token 。如果您将 token 传递给抓取,抓取将只返回该点的 token ,无论是已读还是未读。

乍一看,Apple 似乎正在提供您想要的行为:在一台设备上安装应用程序,开始处理通知,在第二台设备上安装应用程序,并获取所有这些先前的通知以 catch 进度.

不幸的是,正如我在 CKFetchNotificationChangesOperation: why are READ notifications all nil? 中记录的那样,每当我获取通知时,以前标记为“已读”的通知都没有内容。已读通知中的所有信息都丢失了。

在我的场景中,我选择:

  1. 始终在启动时获取最新记录
  2. 使用之前保存的更改 token (如果存在)获取通知
  3. 处理新通知
  4. 将通知标记为已读
  5. 保存最新的更改 token 以供下次提取使用

对于您的场景,您可以尝试:

  1. 使用之前保存的更改 token (如果存在)获取通知
  2. 处理通知(不要将它们标记为已读)
  3. 保存最新的更改 token 以供下次提取使用

您的第一台设备将忽略每次后续提取时的旧通知,因为您是从更改 token 点开始每次提取。您的第二个设备将在第一次执行时以零更改 token 开始,从而接收所有旧通知。

请注意:尽管上述 WWDC 视频明确表示 Apple 会保留所有旧通知,但我没有找到说明他们保留此信息多长时间的文档。它可能是永远的,也可能不是。

更新了通知获取示例

以下是我获取通知、将它们标记为已读以及缓存更改 token 的方式:

@property CKServerChangeToken *notificationServerChangeToken;

然后...

-(void)checkForUnreadNotifications
{
//check for unread cloudkit messages
CKFetchNotificationChangesOperation *op = [[CKFetchNotificationChangesOperation alloc] initWithPreviousServerChangeToken:_notificationServerChangeToken];

op.notificationChangedBlock = ^(CKNotification *notification)
{
//this fires for each received notification. Take action as needed.
};

//maintain a pointer to the op. We will need to look at a property on the
//op from within the completion block. Use __weak to prevent retain problems
__weak CKFetchNotificationChangesOperation *operationLocal = op;

op.fetchNotificationChangesCompletionBlock = ^(CKServerChangeToken *newServerChangeToken, NSError *opError)
{
//this fires once, at the end, after all notifications have been returned.
//this is where I mark the notifications as read, for example. I've
//omitted that step because it probably doesn't fit your scenario.

//update the change token so we know where we left off
[self setNotificationServerChangeToken:newServerChangeToken];

if (operationLocal.moreComing)
{
//more notifications are waiting, recursively keep reading
[self checkForUnreadNotifications];
return;
}
};

[[CKContainer defaultContainer] addOperation:op];
}

要从用户默认设置和检索缓存的更改 token ,我使用以下两个函数:

-(void)setNotificationServerChangeToken:(CKServerChangeToken *)newServerChangeToken
{

//update the change token so we know where we left off
_notificationServerChangeToken = newServerChangeToken;
NSData *encodedServerChangeToken = [NSKeyedArchiver archivedDataWithRootObject:newServerChangeToken];
NSUserDefaults *userSettings = [NSUserDefaults standardUserDefaults];
[userSettings setObject:encodedServerChangeToken forKey:UD_KEY_NOTIFICATION_TOKEN_CKSERVERCHANGETOKEN_PROD];

//Note, the development and production cloudkit environments have separate change tokens. Depending on your needs, you may need to save both.
}

和...

-(void)getNotificationServerChangeToken
{
NSUserDefaults *userSettings = [NSUserDefaults standardUserDefaults];
NSData *encodedServerChangeToken = [userSettings objectForKey:UD_KEY_NOTIFICATION_TOKEN_CKSERVERCHANGETOKEN_PROD];
_notificationServerChangeToken = [NSKeyedUnarchiver unarchiveObjectWithData:encodedServerChangeToken];
}

关于iOS、CloudKit - 我的应用程序启动时是否需要进行提取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42599643/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com