【问题标题】:Keeping a long-term reference to an IOS AddressBook entry保持对 IOS 地址簿条目的长期引用
【发布时间】:2013-02-08 00:24:46
【问题描述】:

鉴于 ABRecordID 可能会在云同步之间发生变化以及在我无法控制的其他情况下,我如何保持对 IOS 通讯录记录的长期引用?

Apple 提供以下指导:

“保持对特定记录的长期引用的推荐方法是存储名字和姓氏,或名字和姓氏的哈希值,以及标识符。当您通过以下方式查找记录时ID,将记录的名称与您存储的名称进行比较。如果它们不匹配,则使用存储的名称查找记录,并为记录存储新的 ID。"

但我不明白这个指导。如果地址簿中可以有重复的名称,并且由于用户可以修改记录中的名称,那么这个建议如何工作?

例如,如果用户修改了地址簿记录的名称,我的例程将无法通过 ABRecordID 找到它,所以如果我认为按我存储的名称哈希搜索我找不到重复的名称而不是新的 ABRecordID对于我之前引用的特定记录?

最后,获得对 IOS 地址簿记录的长期引用的最佳方法是什么?如果上述建议确实有效,我错过了什么?

【问题讨论】:

  • 您能否更具体地说明您要使用永久 ID 完成的工作?如果将其链接到另一个服务、数据库,也许更好的方法是在联系人上创建一些可以跟踪它的东西。真正可悲的是,这在 mac 上不是问题。请参阅:blog.clickablebliss.com/2011/11/07/… 了解更多信息
  • @RichDominelli 我正在尝试将应用程序设置数据与每个联系人相关联,这些联系人可以在恢复或云同步以及重命名和更新后幸存下来。
  • 目前 iOS 不支持每条记录的 uuid 也不支持自定义字段。您可以尝试生成哈希,但正如您所指出的那样,它并不完美。您还可以输入一个自定义标签电话号码,该电话号码对每条记录都是唯一的,但用户也可以轻松破解它。

标签: iphone ios objective-c


【解决方案1】:

最稳健(但并非完全安全)的方法是对 ABRecord 字段进行优先级排序,并将该列表中可用的尽可能多的数据与 ABRecordID 一起存储到您自己的(散列的)私有记录格式中.在检索私人记录时(或在其他方便的时间),您可以验证私人记录是否与 ABRecord 匹配,并通过一系列后备检查来确保其准确无误。

优先级排序示例:

  1. ABRecordID
  2. 名字
  3. 姓氏
  4. 电话号码
  5. 邮政编码

检索记录时,您可以先匹配ABRecordID。如果没有返回结果,您可以搜索FirstName + LastName。然后,您可以将这些结果与 PhoneNumber... 等进行匹配。通过这种方式,您可能会区分 2 个 Bob Smith,因为它们可能有不同的电话号码(或者其中一个可能没有电话号码)。当然,根据您的优先级列表的长度,这种机制会越稳健。

最后的手段是提示用户区分 2 Bob Smiths 和全新的 ABRecordID,其记录在其他方面完全相同——毕竟,这样不方便的提示比允许用户联系要友好得多错误的 Bob Smith(正如我所说,这是最后的手段)。

但是,此 AB 解决方案可能涉及一些同步问题。

对于使用过 iOS 媒体播放器的任何人来说,这是一个熟悉的问题。特别是用户音乐库中的MPMediaItems 有一个属性MPMediaItemPropertyPersistentID,文档将其描述为:

不保证该值在同步/取消同步/同步周期内保持不变。

换句话说,PersistentID 不能保证是持久的。解决方案包括对 MediaItem 属性进行类似的回退检查。

【讨论】:

  • 如何将所有属性组合成一个字符串,然后进行md5编码。您只需检查md5代码是否相等。
  • @frank 如果用户修改记录中的任何信息,解决方案将失败。
  • 这在最新的 API 版本中是否仍然相关?说“abreocord 在设备之间不一致”的文档现在已存档。 latest docs 只说 ABRecord#uniqueId 是独一无二的,似乎没有更多信息。
【解决方案2】:

RecordID 仅在删除或重置时更改,完成此操作后,所有新记录也将具有新的 createdProperty 和 modifiedProperty。

  1. 当我第一次阅读通讯录时,我会将记录的所有条目连同 RecordID 一起保存在我的数据库中。

  2. 我会将联系人上次从联系人同步到我的数据库的时间保存(命名为:lastSyncedTime)并将其存储在某个位置。

我已经完成了第一次同步联系人,现在执行以下操作以便将来随时同步。

在遍历所有记录时,

  1. 检查 createdTime(kABPersonCreationDateProperty) 与 lastSyncedTime。如果 createdTime > lastSyncedTime,则将 recordID 存储在“newRecords”NSArray 中。

  2. 如果 !(步骤 1)然后检查 modifiedDate(kABPersonModificationDateProperty) 与 lastSyncedTime。如果 modifiedDate > lastSyncedTime,则将 recordID 存储在“modifiedRecords”NSArray 中。

  3. if !(1) && !(2) 将所有 recordID 存储在“unModifiedRecords”中。

现在我将从本地数据库中读取所有联系人,

  1. 我将删除所有在“modifiedRecords”或“unModifiedRecords”中找不到的本地数据库记录。

  2. 我将更新本地数据库中的所有“modifiedRecords”。

  3. 我将为“newRecords”中的所有记录创建新记录。

  4. 相应地更新 lastSyncedTime。

【讨论】:

  • 不错。但此方法不适用于 ABRecordRef 组。因为该组没有任何与日期相关的属性...
  • 如果上次同步时间是使用本地日期([NSDate date]),如果用户更改了日期。此方法不起作用。
  • 您可能只需要比较上次修改时间。当记录为 crate 时,创建时间等于上次修改时间。
【解决方案3】:

文档告诉您,您不能将 ABRecordID 视为永久标识符。

考虑这种情况:用户有“Bob Smith”的记录。然后,用户删除他的“Bob Smith”记录,然后通过 iTunes 同步从他的计算机导入他的联系人(创建一个新 ID)。

因此,如果您想保留对现有联系人的永久引用,您可以保留对姓名和 ID 的引用,以暗示它与您之前使用的记录相同 - 但 没有真正的永久引用

如果您保留对地址簿联系人的永久引用,您必须随时准备好处理这样一个事实,即它可能与您以前使用的联系人不同。

【讨论】:

  • 嗯,是的,我认为这就是我在帖子中所说的以及我引用编程指南的原因。我的问题是如何最好地保持长期参考。如果 Bob Smith 被删除然后重新创建,我可以使用他们的建议来处理。如果设备恢复或 MobileMe 重置更改了每个 ID,那么 Apple 的建议似乎行不通。所以(a)我是否正确地假设他们的建议不起作用,(b)如果我是对的,那么人们使用什么方法来正确更新 id 或考虑到地址簿允许他们使用什么其他方法来保持长期参考重名?
  • (A)他们的建议是有效的,并且是最佳实践——您通常可以绑定到您存储的 ID 和姓名组合。 (B)您只需要始终假设最坏的情况是可能(该记录不再是您的应用程序最后一次引用它的记录,并且可能存在与存储名称匹配的重复记录现在)。
  • 我明白了,没有任何方法可以防止以下情况发生吗?地址簿中有两个 Bob Smith。我为两者存储 ABRecordID 和名称哈希。然后我将我的一些应用程序元数据与一个相关联。 iPhone 被重置并重新生成所有 ABRecordID。现在我不知道我为哪个 Bob Smith 关联了元数据,对吗?如果我使用名称搜索,我会得到一个任意的 Bob Smith。
  • 是的。您总是必须为最坏的情况做好准备。可以这样想——它是用户的通讯录——而你是看着它的客人。他们可能随时撕掉这些页面。因此,如果您的应用启动并注意到记录不同,您必须为正常恢复规划一个工作流程。
  • -1 没有办法,但这已经在问题中了...... 与 cmets 这将是 IMO 的答案
【解决方案4】:

【讨论】:

  • 请注意 link-only answers 是不鼓励的,所以答案应该是寻找解决方案的终点(而不是另一个参考中途停留,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,并保留链接作为参考。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多