gpt4 book ai didi

ios - 在线/离线数据管理

转载 作者:技术小花猫 更新时间:2023-10-29 11:04:58 27 4
gpt4 key购买 nike

我必须创建一个功能类似于联系人应用程序的应用程序。您可以在客户的 iPhone 上添加一个联系人,它应该会上传到客户的 iPad 上。如果客户在他们的 iPad 上更新联系人,它应该会在他们的 iPhone 上更新。

其中大部分是相当直接的。我正在使用 Parse.com作为我的后端并使用 Core Data 在本地保存联系人.我遇到的唯一问题是在用户离线时管理联系人。

假设我有一部 iPhone 和一部 iPad。他们两个目前拥有相同版本的在线数据库。我的 iPhone 现在处于离线状态。现在是上午 9 点。

上午 10 点,我在 iPad 上更新联系人的电话号码。它在本地和在线保存更改。上午 11 点,我在 iPhone 上更新了同一联系人的电子邮件地址,但我仍然处于离线状态。

中午,我的 iPhone 连接到互联网并检查服务器是否有变化。它看到它的更改比最新更新更新(检查 updatedAt 时间戳属性),因此它不会下载联系人的新电话号码(“已过时”),而是覆盖电话号码和电子邮件地址(将新电话号码更新为旧版本,因为它在上午 10 点更新电话号码期间处于离线状态,并且其更改据说是最近的)。

我应该如何管理遇到的在线/离线问题,例如上述问题?我能想到的一个解决方案是为联系人的每个属性保留更新的时间戳,而不仅仅是一般的 updatedAt整个联系人的属性,例如什么时候更新名字,什么时候更新姓氏,然后手动检查离线设备是否对每个属性都有最近的更改,而不是覆盖整个对象,但这似乎很草率。

我也想拥有一个 updatedLocallyupdatedOnline每个 Core Data 上的时间戳属性目的。这样,如果两者不匹配,我可以进行差异检查并使用最新的来解决冲突,但这似乎仍然不是最干净的解决方案。有没有其他人遇到过类似的事情?如果是这样,你是如何解决的?

我的想法的伪代码/摘要?涵盖了每个测试用例,但仍然不是很优雅/完整:

Parse.com 上的 2 个实体:联系方式和联系历史

联系人有第一个、最后一个、电话、电子邮件、在线更新

联系人历史记录有一个联系人的主键来引用,并且具有相同的属性但具有历史记录。例如first: [{value:"josue",onlineUpdate:"9AM"},{value:"j",onlineUpdate:"10AM"},{value:"JOSUEESP",onlineUpdate:"11AM"}]
1 核心数据实体,联系人:

联系人有第一个、最后一个电话、电子邮件、onlineUpdate 和 offlineUpdate(重要:这仅在 Core Data 上,不在 Parse 上)

for every contact in parse database as onlineContact {
if onlineContact does not exist in core data {
create contact in core data
}
else {
// found matching local object to online object, check for changes
var localContact = core data contact with same UID as onlineContact
if localContact.offlineUpdate more recent than onlineContact.onlineUpdate {
for every attribute in localContact as attribute {
var lastOnlineValueReceived = Parse database Contact History at the time localContact.onlineUpdate for attribute
if lastOnlineValueReceived == localContact.attribute {
// this attribute did not change in the offline update. use latest available online value
localContact.attribute = onlineContact.attribute
}
else{
// this attribute changed during the more recent offline update, update it online
onlineContact.attribute = localContact.attribute
}
}
}
else if onlineContact.onlineUpdate more recent than localContact.offlineUpdate {
// another device updated the contact. use the online contact.
localContact = offlineContact
}
else{
// when a device is connected to the internet, and it saves a contact
// the offline/online update times are the same
// therefore contacts should be equivalent in this else statement
// do nothing
}
}

TL;DR:您应该如何构建一种用于在线/离线更新的版本控制系统而不会被意外覆盖?我想将带宽使用限制在最低限度。

最佳答案

我建议使用基于 key 的更新而不是基于联系人的更新。
您不应该将整个联系人发送到服务器,在大多数情况下,用户只会更改一些属性(例如“姓氏”通常不会经常更改)。这也减少了带宽使用。
随着离线联系人的应用更改,您发送
您的本地联系人到服务器的旧版本号/上次更新时间戳。服务器现在可以
只需查看您的旧版本号,即可确定您的本地数据是否是最新的。如果您的旧版本号与服务器的当前版本号匹配,则您的客户端无需更新任何其他信息。如果不是这种情况,服务器应向您发送新联系人(在应用您请求的更新后)。
您还可以保存这些提交,这将导致联系历史记录
每次更改 key 时,它不会存储整个联系人,而只会存储更改本身。
一个简单的伪代码实现可能如下所示:

for( each currentContact in offlineContacts ) do
{

if( localChanges.length > 0){ // updates to be made
commitAllChanges();
answer = getServerAnswer();

if(answer.containsContact() == true){
// server sent us a contact as answer so
// we should overwrite the contact
currentContact = answer.contact;
} else {
// the server does not want us to overwrite the contact, so we are up to date!
}
// ...

}
} // end of iterating over contacts

服务器端看起来同样简单:
for (currentContactToUpdate in contactsToUpdate) do 
{
sendBackContact = false; // only send back the updated contact if the client missed updates
for( each currentUpdate in incomingUpdates ) do {
oldClientVersion = currentUpdate.oldversion;
oldServerVersion = currentContact.getVersion();

if( oldClientVersion != oldServerVersion ){
sendBackContact = true;
// the client missed some updates from other devices
// because he tries to update an old version
}

currentContactToUpdate.apply(currentUpdate);

}

if(sendBackContact == true){
sendBack(currentUpdate);
}
}

为了更好地理解工作流程,我将提供一个示例:

早上 8 点,客户端和服务器都是最新的 ,每台设备在线

每个设备都有一个条目(在本例中为一行),用于联系人“Foo Bar”,该条目具有主键 ID。
每个条目的版本都相同,因此所有条目都是最新的。
 _        Server    iPhone    iPad
ID 42 42 42
Ver 1 1 1
First Foo Foo Foo
Last Bar Bar Bar
Mail f@b f@b f@b

(原谅这种糟糕的格式,很遗憾不支持任何类型的表格......)



上午 9 点,您的 iPhone 处于离线状态。您注意到 Foo Bar 的电子邮件已更改为“foo@b” .
您可以像这样更改手机上的联系信息:
UPDATE 42 FROM 1          TO 2             Mail=foo@b
// ^ID ^old version ^new version ^changed attribute(s)

所以现在你手机中的联系人看起来像这样:
 _        iPhone   
ID 42
Ver 2
First Foo
Last Bar
Mail foo@b



上午 10 点,您的 iPad 处于离线状态。你注意到“Foo Bar”实际上写成“Voo Bar” !您可以立即在 iPad 上应用更改。
UPDATE 42 FROM 1 TO 2 First=Voo

请注意,iPad 仍然认为当前版本的 contact 42 是 1。服务器和 iPad 都没有注意到您如何更改邮件地址和增加版本号,因为没有设备连接到网络。这些更改仅在本地存储并在您的 iPad 上可见。


上午 11 点,您将 iPad 连接到网络。 iPad 发送最近的更新
到服务器。之前:
 _        Server    iPad
ID 42 42
Ver 1 2
First Foo Voo
Last Bar Bar
Mail f@b f@b

iPad -> 服务器:
UPDATE 42 FROM 1 TO 2 First=Voo

服务器现在可以看到您正在更新联系人 42 的版本 1。由于版本 1 是当前版本,您的客户端是最新的(在您离线时没有提交任何更改)。
服务器 -> iPad
UPDATED 42 FROM 1 TO 2 - OK

之后:
 _        Server    iPad
ID 42 42
Ver 2 2
First Voo Voo
Last Bar Bar
Mail f@b f@b



凌晨 12 点,您断开了 iPad 与网络的连接并连接了 iPhone。
iPhone 尝试提交最近的更改。之前:
 _        Server    iPhone
ID 42 42
Ver 2 2
First Voo Voo
Last Bar Bar
Mail f@b foo@b

iPhone -> 服务器
UPDATE 42 FROM 1 TO 2 Mail=foo@b

服务器会注意到您如何尝试更新同一联系人的旧版本。
他会应用你的更新,因为它比 iPad 的更新更新,但是
将向您发送新的联系数据,以确保您也获得更新的名字。之后:
 _        Server    iPhone
ID 42 42
Ver 2 2
First Voo Voo
Last Bar Bar
Mail foo@b foo@b

服务器 -> iPad
UPDATED 42 FROM 1 TO 3 - Ver=2;First=Voo;.... // send the whole contact
/* Note how the version number was changed to 3, and not to 2, as requested.
* If the new version number was (still) 2 the iPad would miss the update
*/

下次您的 iPad 连接到网络并且没有任何更改要提交时,应该只发送联系人的当前版本,看看它是否仍然是最新的。

现在您已经提交了两个离线更改,而不会相互覆盖。
您可以轻松扩展这种方法以及一些优化。例如:
  • 如果客户端尝试更新旧版本的联系人,请不要将整个联系人作为答复发送给他们。而是将他们错过的提交发送给他们,让他们自己更新他们的联系方式。如果您存储了大量有关客户端的信息并且希望在更新之间进行很少的更改,这将非常有用。
  • 如果客户更新了有关联系人的所有信息,我们可以假设他不需要知道错过的更新,但是我们会让他知道他错过的所有信息(但它不会/应该对他没有影响)

  • 我希望这会有所帮助。

    关于ios - 在线/离线数据管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31102357/

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