Search code examples
objective-cmultithreadingcontactsaddressbook

multithreading error with ABAddressBookRef


I have problems with the threads at the recorer for, I have a contact list of 600 and 6 shows me the following error.

Thread 1: EXC_BAD_ACCESS (code = 1, address = 0x29)

is the following code

-(void) actualizarContactos
{
    CFErrorRef *error = nil;

    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);

    __block BOOL accessGranted = NO;
    if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
            accessGranted = granted;
            dispatch_semaphore_signal(sema);
        });
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

    }
    else { // we're on iOS 5 or older
        accessGranted = YES;
    }

    if (accessGranted) {
        //ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
        ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
        CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
        CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
       // NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];

        NSMutableArray *TodosContactos = [[NSMutableArray alloc]init];

        //consultar numero de contactos anteriores

        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

        NSString *numeroContactos = [userDefaults objectForKey:@"numeroContactos"];

        int numContactos = [numeroContactos intValue];

        //validar si hay contactos nuevos
        if(numContactos != nPeople)
        {


        for (int i = 0; i < nPeople; i++)
        {
            //  NSMutableArray *contacto = [[NSMutableArray alloc]init];

            ContactsData *contacts = [ContactsData new];

            ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);

            //get First Name and Last Name

            // NSMutableArray *name = [[NSMutableArray alloc]init];

            if((__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty))
            {
            contacts.firstName = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
            }
            if((__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty))
            {
            contacts.lastName =  (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
            }

            if (!contacts.firstName) {
                contacts.firstName = @"";
            }
            if (!contacts.lastName) {
                contacts.lastName = @"";
            }

            contacts.compositeName = [NSString stringWithFormat:@"%@ %@",contacts.firstName,contacts.lastName];


            // get contacts picture, if pic doesn't exists, show standart one

            Boolean sw = true;

               NSData  *imgData = (__bridge_transfer NSData *)ABPersonCopyImageData(person);
               contacts.photo = [UIImage imageWithData:imgData];
               if (!contacts.photo) {
                   sw = false;
                   contacts.photo = [UIImage imageNamed:@"[email protected]"];
            }
            //get Phone Numbers

                NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];

            Boolean swContactoSiguiente = true;

                ABMultiValueRef multiPhones = ABRecordCopyValue(person, kABPersonPhoneProperty);
               for(CFIndex i=0;i<ABMultiValueGetCount(multiPhones);i++)
               {

                   CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
                   NSString *phoneNumber = (__bridge_transfer NSString *) phoneNumberRef;

                   //prueba
                  // NSLog([NSString stringWithFormat:@"name: %@ tel: %@",contacts.compositeName,phoneNumbers]);

                   if(![phoneNumber hasPrefix:@"+"] && ![phoneNumber hasPrefix:@"00"] && ![phoneNumber hasPrefix:@"011"])
                   {
                       swContactoSiguiente = true;
                   }
                   else
                   {
                       swContactoSiguiente = false;
                       [phoneNumbers addObject:phoneNumber];
                   }



               }

            if(swContactoSiguiente)
            {
               continue;
            }



            contacts.phones = phoneNumbers;



            //get Contact email

               NSMutableArray *contactEmails = [NSMutableArray new];
               ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty);

                for (CFIndex i=0; i<ABMultiValueGetCount(multiEmails); i++) {
                   CFStringRef contactEmailRef = ABMultiValueCopyValueAtIndex(multiEmails, i);
                NSString *contactEmail = (__bridge_transfer NSString *)contactEmailRef;

           [contactEmails addObject:contactEmail];
            // NSLog(@"All emails are:%@", contactEmails);

              }

            //  [contacts setEmails:contactEmails];
            contacts.emails = contactEmails;



            //guardar en CoreData

            if(contacts.phones.count != 0)
            {
                contacts.phone = [self deleteSpace:contacts.phones[0]];
            }

            //se valida existencia del phone en la base de datos
            if([self consultarTelefono:contacts.phone])
            {

            AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];

            NSManagedObjectContext *context = [appDelegate managedObjectContext];
            NSManagedObject *newContact;
            newContact = [NSEntityDescription insertNewObjectForEntityForName:@"Contacts" inManagedObjectContext:context];

            [newContact setValue: contacts.compositeName forKey:@"compositeName"];
            [newContact setValue: contacts.firstName forKey:@"firstName"];
            [newContact setValue: contacts.lastName forKey:@"lastName"];
            [newContact setValue: contacts.phone forKey:@"phone"];

            NSNumber *fv = [NSNumber numberWithBool:false];
            [newContact setValue:fv forKey:@"favorite"];
            if(sw)
            {
            [newContact setValue: imgData forKey:@"photo"];
            }


            NSError *error;
            [context save:&error];




          //  [items addObject:contacts];
            }

            //ABRecordRef
           // CFRelease(addressBook2);
          //  CFRelease(person);
          //  CFRelease(source2);
           // CFRelease(allPeople2);
           // NSLog([NSString stringWithFormat:@"%d",i]);
          }

            // se guarda en memoria numero de contactos
            NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

            [defaults setObject:[NSString stringWithFormat:@"%d",(int)nPeople] forKey:@"numeroContactos"];

            [defaults synchronize];

        }



    }
    else
    {
        UIAlertView *alertFailSave = [[UIAlertView alloc] initWithTitle:@"Error"
                                                                message:NSLocalizedString(@"TEXT_ACCESS", nil)
                                                               delegate:nil
                                                      cancelButtonTitle:NSLocalizedString(@"LO_BUTTON_OK", nil)
                                                      otherButtonTitles:nil];        
        [alertFailSave show];
    }

}

Solution

  • la corrección fue cambiar el siguiente codigo:

    // ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error); // ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook); // CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName); // CFIndex nPeople = ABAddressBookGetPersonCount(addressBook); // NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];

    por este.

        ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
        CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
        CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);