Given that an ABRecordID can change between cloud syncs and under other circumstances out of my control, how can I maintain a long-term reference to an IOS address book record?

Apple provides the following guidance:

"The recommended way to keep a long-term reference to a particular record is to store the first and last name, or a hash of the first and last name, in addition to the identifier. When you look up a record by ID, compare the record’s name to your stored name. If they don’t match, use the stored name to find the record, and store the new ID for the record."

But I don't understand this guidance. If the address book can have duplicate names in it AND since users can modify the name in a record how could this advice work?

For example, if the user modifies the name of an address book record my routine will fail to find it by ABRecordID so if I think search by the name hash I stored couldn't I find a duplicate name instead of the new ABRecordID for that specific record I previously referenced?

In the end, what is the BEST way to get a long-term reference to an IOS AddressBook record? And if the above advice really does work what am I missing?

Could you be a little more specific on what you are trying to accomplish with the permanent id? If it to link it to another service, database, perhaps a better approach would be to create something on the contact you can track it with. The really sad thing is this is not a problem on the mac. See : blog.clickablebliss.com/2011/11/07/… for more info
–
Rich DominelliFeb 14 '13 at 14:59

@RichDominelli I am trying to associate application settings data with each contact that can survive a restore or cloud sync and of course renames and updates.
–
robert_difalcoFeb 20 '13 at 19:44

Right now iOS does not support the uuid for each record nor does it support custom fields. You could try generating a hash but as you indicated its not perfect. You could also put in a custom label phone number which is unique to each record but again the user can easily break it.
–
Rich DominelliFeb 23 '13 at 1:01

3 Answers
3

The most robust (yet not completely failsafe) approach would be to come up with a priority ranking of ABRecord fields and store as much from that list as is available, along with the ABRecordID, into your own (hashed) private record format. When retrieving a private record (or at another convenient time), you can verify that the private record matches the ABRecord and work through a series of fallback checks to ensure it's accurate.

Example priority ranking:

ABRecordID

FirstName

LastName

PhoneNumber

ZipCode

When retrieving a record you can first match the ABRecordID. If that returns no results, you can do a search for FirstName + LastName. You can then match those results against PhoneNumber... etc. In this way you could potentially distinguish between 2 Bob Smiths, as they may have different phone numbers (or one may not have a phone number). Of course, depending on how long your priority list is, the more robust this mechanism will be.

The last resort would be prompting the user to distinguish between 2 Bob Smiths with brand new ABRecordID's whose records are otherwise identical -- after all, such an inconvenient prompt would be far more friendly than allowing the User to contact the wrong Bob Smith (and as I said, would be a last resort).

This solution for AB may involve some synchronization issues, however.

This is a familiar problem for anyone who has worked with the iOS Media Player. Specifically MPMediaItems in the User's Music Library have a property MPMediaItemPropertyPersistentID which the docs describe as:

The value is not guaranteed to persist across a sync/unsync/sync cycle.

In other words, the PersistentID is not guaranteed to be persistent. Solutions for this include doing similar fallback checks on MediaItem properties.

The documentation is communicating to you that you can't count on ABRecordID as a permanent identifier.

Consider this scenario: The user has a record for "Bob Smith". The user then deletes his "Bob Smith" record and then imports his contacts from his computer (creating a new ID) through iTunes sync.

So if you want to keep a permanent reference to an existing contact, you can keep a reference to the name and id as a hint that it is the same record you used before- but there is no real permanent reference.

If you keep a permanent reference to an address book contact, you must always be ready to deal with the fact that it may not be the same contact you used before.

Well yes, I think that's what I said in my post and why I quoted the programming guide. My question is how best to keep a long term reference. If Bob Smith is deleted then recreated, I can handle that using their advice. If a device is restored or a MobileMe reset changes every ID then it seems as though the Apple advice would not work. So (a) am I right in assuming their advice wont work and (b) if I am right then what approach to people use to properly update the ids or what other methods do they use to keep a long term reference considering that the AddressBook allows duplicate names?
–
robert_difalcoFeb 8 '13 at 15:46

(A)Their advice works and is the best practice - you will usually be able to tie back to your stored ID and name combo. (B)You just always have to assume the worst case scenario is possible (that the record no longer is the record it was the last time your app referenced it and there may be duplicate records matching the stored name now).
–
Fruity GeekFeb 8 '13 at 18:26

Just so I understand, there is no method that prevents the following from happening? There are two Bob Smith's in the Address Book. I store the ABRecordID and name hash for both. Then I associate some of my app metadata with one. The iPhone is reset and all ABRecordIDs are regenerated. NOW I can NOT know for which Bob Smith I have associated meta data, correct? If I fall back on a name search I will get an arbitrary Bob Smith.
–
robert_difalcoFeb 8 '13 at 18:37

Yes. You always have to be ready for the worst case scenario. Think of it this way - it's the USER's address book - and you are a guest looking at it. They may rip out the pages at any time. So if your app launches and notices the records are different, you have to plan a workflow for graceful recovery.
–
Fruity GeekFeb 8 '13 at 18:49

-1 there is no way but that was already in the question... with the comments this would be an answer IMO
–
Daij-DjanFeb 17 '13 at 0:31