Had the same problem, so I've decided to gather all the information on topic.
From the Address Book Programming Guide (iOS)
Every record in the Address Book database has a unique record
identifier. This identifier always refers to the same record, unless
that record is deleted or the data is reset. Record identifiers can be
safely passed between threads. They are not guaranteed to remain the
same across devices
From the Address Book Programming Guide (OSX)
Each group and person has a unique identifier. It’s set when the
record is created, and guaranteed never to change even if a user
changes the group’s or person’s name or other information. Use this
identifier if your application needs to store a reference to a group
or person. For more information, see the ABRecord method uniqueId.
But appears that in reality it does change for example when user turns off/on iCloud :
http://mjtsai.com/blog/2011/11/07/kabuidproperty/
So the best way to do this is :
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.
also worth reading:
Keeping a long-term reference to an IOS AddressBook entry
Regarding the new Contacts Framework :
CNContact.identifier
It is recommended that you use the identifier when re-fetching the
contact. An identifier can be persisted between the app launches. Note
that this identifier only uniquely identifies the contact on the
current device.