2011-09-19 19 views
6

Tengo una aplicación que se cuelga ocasionalmente debido a la matriz devuelta por ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering() que tiene un tamaño diferente a ABAddressBookGetPersonCount(). El shell del código se muestra a continuación. Por lo general, nPeople es del mismo tamaño que la matriz. Sin embargo, en el iPhone de un usuario (o al menos, según lo informado por un usuario), nPeople es casi dos veces más grande. Puedo detener el bloqueo utilizando el tamaño de la matriz, en lugar de ABAddressBookGetPersonCount(). Sin embargo, no estoy seguro de si esto significa que no estoy accediendo a todos los contactos en el iPhone.ABAddressBookCopyArrayOfAllPeople y ABAddressBookGetPersonCount devuelve diferentes tamaños

  • ¿Alguien ha encontrado este problema antes?
  • ¿Por qué los números serían diferentes?

Me preguntaba si era algo relacionado con los contactos almacenados en Grupos (no sé si hay grupos, solo una idea). Además, desde la dirección de correo electrónico del usuario, sospecho que usan MobileMe. Me preguntaba si la sincronización con MobileMe crearía duplicados con un recordId diferente, pero no eliminaría el contacto existente, al menos no tan lejos como va ABAddressBookGetPersonCount().

EDIT: He investigado esto un poco más y tengo una idea bastante buena de la causa del problema. Como quería un conjunto ordenado de contactos, utilicé ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(). Esto requiere una fuente de libreta de direcciones: utilicé la fuente predeterminada. Creo que puede haber varias fuentes: la fuente local más otras como Exchange y MobileMe. Por lo tanto, mi matriz terminará con solo los contactos locales, mientras que el número devuelto por ABAddressBookGetPersonCount() incluirá todas las fuentes, de ahí mi bloqueo. Por lo tanto, creo que sería mejor trabajar con los datos locales en mi aplicación y usar el tamaño de matriz devuelto por ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering en lugar de ABAddressBookGetPersonCount.

CFArrayRef allPeople = InSourceWithSortOrdering(addressBook, source, kABPersonSortByLastName); 

    CFIndex nPeople = ABAddressBookGetPersonCount(addressBook); 

    for (int i = 0; i < nPeople; i++) 
    { 
     ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i); 
    } 

Respuesta

13

ABAddressBookGetPersonCount Y ABAddressBookCopyArrayOfAllPeople da diferentes matrices.

ABAddressBookGetPersonCount: devuelve el número de registros personales en una libreta de direcciones. ABAddressBookCopyArrayOfAllPeople - Devuelve todos los registros personales en una libreta de direcciones.

Así que algunas veces la misma persona puede tener registros extra. Es por eso que puede obtener diferentes tamaños.

+0

que significa que ABAddressBookGetPersonCount siempre debe ser menor que ABAddressBookCopyArrayOfAllPeople? –

+0

Depende. Será diferente si la misma persona puede tener registros adicionales. Si cada persona tiene un número de contacto. Entonces ambos serán lo mismo. :) @NikitaP –

9

Hoy encuentro este problema. Mi aplicación también falla en algunos iDevices especiales.

código:

ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook); 
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByLastName); 

    CFIndex nPeople = ABAddressBookGetPersonCount(addressBook); 

    for (int i = 0; i < nPeople; i++) { 
     ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i); 
     // more thing with `person` 
    } 

Pero a veces se bloqueará. Agregando algunos puntos de interrupción, encontré que el recuento de allPeople es menor que nPeople.

Al buscar en Google, encontré this article. Descubrí que tal vez hay algo mal con ABAddressBookCopyDefaultSource. Aquí obtuve la fuente predeterminada , tengo que obtener todas las fuentes en su lugar.

código:

CFArrayRef sources = ABAddressBookCopyArrayOfAllSources(addressBook); 

CFIndex sourceCount = CFArrayGetCount(sources); 

for (CFIndex i = 0; i < sourceCount; i++) { 
    ABRecordRef currentSource = CFArrayGetValueAtIndex(source, i); 
    int sourceType = [(__bridge NSNumber *)ABRecordCopyValue(currentSource, kABSourceTypeProperty) intValue]; 
    switch (sourceType) { 

     case kABSourceTypeCardDAV: 
      NSLog(@"kABSourceTypeCardDAV"); 
      break; 

     case kABSourceTypeCardDAVSearch: 
      NSLog(@"kABSourceTypeCardDAVSearch"); 
      break; 

     case kABSourceTypeExchange: 
      NSLog(@"kABSourceTypeExchange"); 
      break; 

     case kABSourceTypeExchangeGAL: 
      NSLog(@"kABSourceTypeExchangeGAL"); 
      break; 

     case kABSourceTypeLDAP: 
      NSLog(@"kABSourceTypeLDAP"); 
      break; 

     case kABSourceTypeLocal: 
      NSLog(@"kABSourceTypeLocal"); 
      break; 

     case kABSourceTypeMobileMe: 
      NSLog(@"kABSourceTypeMobileMe"); 
      break; 

     default: 
      break; 
    } 
    CFArrayRef allPeopleInSource = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, currentSource, kABPersonSortByLastName); 
    NSLog(@"Count of allPeopleInSource: %i", CFArrayGetCount(allPeopleInSource)); 
} 

Entonces tuve

kABSourceTypeCardDAV 
    Count of allPeopleInSource: 7 

lo que significa que sólo hay una fuente y sólo 7 registros en esa fuente.

¡Pero en mi libreta de direcciones tengo 79 contactos!

Luego cometí un error. Pasé la sources-ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering, al igual que este:

CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, sources, kABPersonSortByLastName); 

¿Cuántos miembros en allPeople?

72 !!!

Exactamente el recuento de registros que no están en sources.

Pasé un CFArrayRef a ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering como el segundo parámetro, que espera un ABRecordRef. ¿Qué pasa si paso nil?

último, tengo los códigos:

CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, nil, kABPersonSortByLastName); 

    CFIndex nPeople = ABAddressBookGetPersonCount(addressBook); 

    for (int i = 0; i < nPeople; i++) { 
     ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i); 
     // more thing with `person` 
    } 

Ahora puede conseguir todos los contactos de mi libreta de direcciones.

¡Funciona bien en todos mis dispositivos!

Lo siento mucho por mi mala Inglés ...

Con suerte, esta respuesta puede ayudar.

Nota: Ahora bien, no entiendo lo que es source en la libreta de direcciones exactamente, ¿Alguien puede ayudarme?

+0

Buena respuesta. A veces, todos los contactos en su libreta de direcciones pueden no ser de una sola fuente. Puede ser de Facebook, diferentes gmails, etc. Entonces, si no especificas una fuente, obtienes todos los contactos. – Kaey

Cuestiones relacionadas