【发布时间】:2015-06-28 16:56:05
【问题描述】:
我必须创建一个功能类似于联系人应用程序的应用程序。您可以在客户的 iPhone 上添加联系人,它应该会上传到客户的 iPad。如果客户在他们的 iPad 上更新联系人,它应该在他们的 iPhone 上得到更新。
其中大部分都是相当直接的。我使用Parse.com 作为我的后端并使用Core Data 在本地保存联系人。我遇到的唯一问题是在用户离线时管理联系人。
假设我有一部 iPhone 和一部 iPad。他们俩目前都拥有相同版本的在线数据库。我的 iPhone 现在离线了。现在是上午 9 点。
上午 10 点,我在 iPad 上更新联系人的电话号码。它在本地和在线保存更改。上午 11 点,我在 iPhone 上更新了同一联系人的电子邮件地址,但仍处于离线状态。
中午,我的 iPhone 连接到互联网并检查服务器是否有更改。它发现其更改比最新更新更新(检查updatedAt 时间戳属性),因此它不会下载联系人的新电话号码(“已过时”),而是覆盖电话号码以及电子邮件地址(将新电话号码更新为旧版本,因为它在上午 10 点更新电话号码期间处于离线状态,并且其更改应该是最近的)。
我应该如何处理上面遇到的在线/离线问题?我能想到的一个解决方案是在联系人的每个属性上保持更新的时间戳,而不仅仅是整个联系人的通用 updatedAt 属性,例如什么时候更新名字,什么时候更新姓氏,然后手动检查离线设备是否对每个属性都有更新,而不是覆盖整个对象,但这似乎很草率。
我还考虑在每个 Core Data 对象上设置一个 updatedLocally 和 updatedOnline 时间戳属性。这样,如果两者不匹配,我可以进行差异检查并使用最新的冲突来解决,但这似乎仍然不是最干净的解决方案。有没有其他人遇到过类似的事情?如果有,你是怎么解决的?
我认为的伪代码/摘要?涵盖了所有测试用例,但仍然不是很优雅/完整:
Parse.com 上的 2 个实体:联系方式和联系历史记录
联系人有first、last、phone、email、onlineUpdate
联系人历史记录具有要引用的联系人的主键和相同的属性,但具有历史记录。例如first: [{value:"josue",onlineUpdate:"9AM"},{value:"j",onlineUpdate:"10AM"},{value:"JOSUEESP",onlineUpdate:"11AM"}]
Core Data 上的 1 个实体,联系人:
Contact 有第一部、最后一部电话、电子邮件、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:您应该如何构建一种用于在线/离线更新而不会意外覆盖的版本控制系统?我想将带宽使用限制到最低限度。
【问题讨论】:
-
有一个类似的问题,并用你的第一个解决方案解决了这个问题,每个键都有一个 updatedAt 字段。当然不是很干净,但似乎是防止意外覆盖的最安全的解决方案......
-
有一个适用于 iOS 的 Parse SDK,它包含离线缓存。为什么不使用它并让 Parse 以专有方式处理时间戳?
-
我在这里进行了调查:stackoverflow.com/questions/31091258/…,但这似乎不是我的解决方案。如果您能想出一种仅使用 Parse 来实现我需要的方法,我很想听听!
-
在这种情况下,也许将 Parse 与 Realm 结合起来? realm.io 至少可以减轻将对象转换为 JSON 的负担
-
为什么要将我的数据转换为
JSON? Parse 提供了一个易于操作的PFObject。
标签: ios database algorithm core-data parse-platform