El delegado de ABPeoplePicker devuelve un identificador incorrecto cuando los numbers de teléfono de Exchange y iCloud están en la misma input

Estoy teniendo un problema donde el ABPeoplePickerNavigationController parece estar devolviendo el identificador incorrecto para los contactos que tienen numbers de teléfono sincronizados tanto de Exchange como de iCloud. Mi aplicación se ejecuta en iOS 7.1 y se comstack con iOS 7.1 SDK.

TL; DR: en la callback delegada del delegado de personas obtengo el identificador incorrecto cuando tengo un contacto que tiene los numbers de teléfono de Exchange y iCloud fusionados.

Respuesta preventiva: Sí, estoy llamando a ABMultiValueGetIndexForIdentifier.

Este problema solo ocurre cuando tengo un solo contacto con los numbers de teléfono de Exchange e iCloud. Corrí una versión anterior de la aplicación comstackda con iOS 6.1 SDK y no tiene el problema cuando se ejecuta en iOS 7.1.

He simplificado la testing hasta:

iPhone está registrado en iCloud con la synchronization de contactos habilitada. El iPhone también está configurado para revisar el correo con Exchange. A cambio. Tengo un contacto llamado "Foo Bar" con tres numbers de teléfono y este contacto se muestra correctamente en iPhone. En este punto, todo funciona como se esperaba en mi aplicación:

  • Trabajo: 212-111-1111
  • Móvil: 212-222-2222
  • Inicio: 212-333-3333
  • Fax de trabajo: 212-444-4444

iPad está registrado en iCloud con la synchronization de contactos habilitada. El correo electrónico no está configurado en este dispositivo. Creé un usuario llamado "Foo Bar" con dos numbers de teléfono:

  • Fax de inicio: 212-555-5555
  • Fax de trabajo: 212-666-6666

Después de que iCloud sincroniza los contactos, veo que "Foo Bar" tiene 6 numbers de teléfono en la aplicación de contactos iOS en el iPhone. Marcar desde la aplicación de contactos iOS marca el número correcto.

En mi aplicación, estoy mostrando un ABPeoplePickerNavigationController. En la callback delegada recibo el número de teléfono incorrecto.

En el selector de personas veo el contacto con los 6 numbers de teléfono en este order:

  • Trabajo: 212-111-1111
  • Fax de trabajo: 212-444-4444
  • Inicio: 212-333-3333
  • Móvil: 212-222-2222
  • Fax de inicio: 212-555-5555
  • Fax de trabajo: 212-666-6666

En el delegado, estoy mostrando todos los numbers de teléfono y siempre se muestran en este order. Parece que las inputs de iCloud están en la list encima de los numbers de Exchange (no es importante).

  • xindex: 0 teléfono: (212) 555-5555
  • xindex: 1 teléfono: (212) 666-6666
  • xindex: 2 teléfono: (212) 111-1111
  • xindex: 3 teléfono: (212) 444-4444
  • xindex: 4 teléfono: (212) 333-3333
  • xindex: 5 teléfono: (212) 222-2222

Cuando selecciono cada input en el selector de personas, obtengo estos resultados en el delegado selector de personas:

  • Teléfono del trabajo: identificador = 0 índice = 0 teléfono = (212) 555-5555 (equivocado: debería ser 212-111-1111)
  • Fax de trabajo: identificador = 1 índice = 1 teléfono = (212) 666-6666 (incorrecto: debería ser 212-444-4444)
  • Inicio: identificador = 2 índice = 2 teléfono = (212) 111-1111 (incorrecto: debería ser 212-333-3333)
  • Móvil: identificador = 3 índice = 3 teléfono = (212) 444-4444 (incorrecto: debería ser 212-222-2222)
  • Fax de inicio: identificador = 0 índice = 0 teléfono = (212) 555-5555 (correcto)
  • Fax de trabajo: identificador = 1 índice = 1 teléfono = (212) 666-6666 (correcto)

Parece que el identificador que se pasa al delegado no es correcto, ya que 0 y 1 se utilizan para 2 inputs diferentes. También podría ser que el identificador para la asignación de índices tampoco sea correcto.

Aquí está mi callback delegada simplificada:

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier { if (property == kABPersonPhoneProperty) { ABMutableMultiValueRef multi = ABRecordCopyValue(person, property); if (multi != NULL) { //Display all the phone numbers for the object CFIndex xcount = ABMultiValueGetCount(multi); NSLog(@"xcount = %lu", (unsigned long)xcount); for (CFIndex xindex = 0 ; xindex < xcount ; ++xindex) { CFStringRef xphone = (CFStringRef)ABMultiValueCopyValueAtIndex(multi, xindex); NSLog(@"xindex:%ld phone:%@", (long)xindex, (__bridge NSString*)xphone); if (xphone) { CFRelease(xphone); } } //Display the selected phone number CFIndex itemIndex = ABMultiValueGetIndexForIdentifier(multi, identifier); CFStringRef phone = (CFStringRef)ABMultiValueCopyValueAtIndex(multi, itemIndex); NSLog(@"identifier:%ld itemIndex:%ld phone:%@", (long)identifier, (long)itemIndex, (__bridge NSString*)phone); if (phone) { CFRelease(phone); } CFRelease(multi); } } return NO; } 

Espero ver un identificador diferente para cada número de teléfono que se asigne al número de índice correcto. ¿Hay un paso que me falta? ¿Esto es un error en iOS 7?

Cualquier ayuda o idea es apreciada.

ABMultiValueGetIndexForIdentifier () (o los datos detrás de él) definitivamente se rompe en iOS 8 y 9. No puedo decir para iOS 7 ya que no teníamos seguimiento de fallas en ese entonces. Ejemplo:

  • Tener un nuevo contacto con 2 direcciones
  • Los identificadores ahora son (0, 1) y los índices correspondientes (0, 1) lo cual es correcto
  • Eliminar la primera dirección
  • El identificador de la dirección restante es (1) y el índice (-1)

Que el identificador sea 1 es comprensible, ya que es un identificador. Pero el índice debería ser 0. Lo que sucede se vuelve más obvio cuando usa 3 direcciones:

  • (0, 1, 2) y (0, 1, 2)
  • Eliminar la primera dirección
  • Se convierte (1, 2) y (1, -1)
  • Al hacer clic en la primera dirección, regresa el segundo
  • Al hacer clic en la segunda dirección, se produce un locking (si no se busca el índice -1 en el que no debería tener que hacerlo en primer lugar)

ABMultiValueGetIndexForIdentifier parece devolver el identificador si el id existe como un índice o -1 si el id excede el range del índice.

Traté de atacar desde un ángulo diferente, pero ABMultiValueGetIdentifierAtIndex también parece roto. Así que iterating sobre las inputs tampoco ayuda. ABMultiValueGetIdentifierAtIndex siempre parece devolver el índice mismo (iOS 9).

Hasta el momento tengo que asumir que este es un error en iOS. Si utilizo mi contacto de testing en otras aplicaciones, parece que tienen exactamente el mismo problema. Dado sus datos, parece que los identificadores y el mapeo de ID a índice realmente están rotos. Para mí los identificadores eran razonables (al less).

Creo que los informes no ayudarán ya que ABPeoplePicker se descontinuó con iOS 9.