2015-08-19 5 views
1

Я использую ABAddressBook, я могу отображать каждый контакт, но у меня есть дублированный контакт.Дублированный контакт с ABAddressBook

Я читал эту тему: Dealing with duplicate contacts due to linked cards in iOS' Address Book API, но не может решить проблему.

Я хотел бы использовать этот код в шахте, но я не удается ..:

NSMutableSet *unifiedRecordsSet = [NSMutableSet set]; 

ABAddressBookRef addressBook = ABAddressBookCreate(); 
CFArrayRef records = ABAddressBookCopyArrayOfAllPeople(addressBook); 
for (CFIndex i = 0; i < CFArrayGetCount(records); i++) 
{ 
    NSMutableSet *contactSet = [NSMutableSet set]; 

    ABRecordRef record = CFArrayGetValueAtIndex(records, i); 
    [contactSet addObject:(__bridge id)record]; 

    NSArray *linkedRecordsArray = (__bridge NSArray *)ABPersonCopyArrayOfAllLinkedPeople(record); 
    [contactSet addObjectsFromArray:linkedRecordsArray]; 

    // Your own custom "unified record" class (or just an NSSet!) 
    DAUnifiedRecord *unifiedRecord = [[DAUnifiedRecord alloc] initWithRecords:contactSet]; 

    [unifiedRecordsSet addObject:unifiedRecord]; 
    CFRelease(record); 
} 

CFRelease(records); 
CFRelease(addressBook); 

_unifiedRecords = [unifiedRecordsSet allObjects]; 

Вот мой код:

- (void)getPersonOutOfAddressBook 
{ 
    //1 
    CFErrorRef error = NULL; 
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error); 

    if (addressBook != nil) { 
     NSLog(@"Succesful."); 

     //2 
     NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); 


     //3 
     NSUInteger i = 0; for (i = 0; i < [allContacts count]; i++) 
     { 
      Person *person = [[Person alloc] init]; 
      ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i]; 

      //4 
      NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, 
                        kABPersonFirstNameProperty); 
      if (firstName == nil) 
      { 
       firstName = @""; 
      } 
      NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty); 
      if (lastName == nil) 
      { 
       lastName = @""; 
      } 
      NSString *fullName = [NSString stringWithFormat:@"%@ %@", firstName, lastName]; 

      person.firstName = firstName; person.lastName = lastName; 
      person.fullName = fullName; 



      //phone 
      //5 
      ABMultiValueRef phones = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty); 

      //6 
      NSUInteger j = 0; 
      for (j = 0; j < ABMultiValueGetCount(phones); j++) { 
       NSString *phone = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, j); 

       if (j == 0) { 
        person.mainNumber = phone; 
       } 
       else if (j==1) person.secondNumber = phone; 
      } 

      //7 
      [person.mainNumber stringByReplacingOccurrencesOfString:@" " withString:@""]; 
      [person.mainNumber stringByReplacingOccurrencesOfString:@"(" withString:@""]; 
      [person.mainNumber stringByReplacingOccurrencesOfString:@")" withString:@""]; 
      [person.mainNumber stringByReplacingOccurrencesOfString:@"+336" withString:@"06"]; 
      [self.tableData addObject:person]; 
      [self.contact addObject:person.fullName]; 

     } 

     //8 
     CFRelease(addressBook); 
    } else { 
     //9 
     NSLog(@"Error reading Address Book"); 
    } 
    NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"fullName" ascending:YES]; 
    [self.tableData sortUsingDescriptors:[NSArray arrayWithObject:sorter]]; 

} 
+0

Несвязанный, но если вы исправили некоторые утечки памяти оригинала, но представили один из своих: вы должны «CFRelease (phones)». Кроме того, вы делаете некоторые замены строк в главном номере телефона, но ничего не делаете с этими заменами, отбрасывая их. Если вы хотите это сделать, изменчивая строка, вероятно, имеет смысл. – Rob

+0

@Rob У меня снова возникли проблемы, я использовал self.contact (NSMutableArray) для добавления только fullName для сортировки с разделами. Я обновляю свой код, чтобы показать вам это. Я не знаю, как исправить только с помощью self.tableData в ViewDidLoad. Мне нужно получить доступ только к person.fullName для localizedCaseInsensitiveCompare – Viny76

+1

@ Rob Хорошо, сделано. Большое спасибо за Вашу помощь !!! – Viny76

ответ

3

Если вы хотите, чтобы избежать добавления дубликатов , вероятно, проще всего построить набор значений ABRecordID, которые уже добавили что-то, и добавить только контакт, если он уже не существует в этом наборе:

self.tableData = [NSMutableArray array]; 
NSMutableSet *foundIDs = [NSMutableSet set]; 

NSArray *allContacts = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook)); 

for (id record in allContacts) { 
    ABRecordRef contactPerson = (__bridge ABRecordRef)record; 
    ABRecordID recordId = ABRecordGetRecordID(contactPerson); 
    if (![foundIDs containsObject:@(recordId)]) { 
     Person *person = [[Person alloc] init]; 

     // get name 

     person.firstName = CFBridgingRelease(ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty)) ?: @""; 
     person.lastName = CFBridgingRelease(ABRecordCopyValue(contactPerson, kABPersonLastNameProperty)) ?: @""; 
     person.fullName = [NSString stringWithFormat:@"%@ %@", person.firstName, person.lastName]; 

     // get phones 

     ABMultiValueRef phones = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty); 
     for (NSUInteger j = 0; j < ABMultiValueGetCount(phones); j++) { 
      // I presume you meant to use mutable string and `replaceOccurrencesOfString`: 

      NSMutableString *phone = [CFBridgingRelease(ABMultiValueCopyValueAtIndex(phones, j)) mutableCopy]; 

      [phone replaceOccurrencesOfString:@" " withString:@"" options:0 range:NSMakeRange(0, phone.length)]; 
      [phone replaceOccurrencesOfString:@"(" withString:@"" options:0 range:NSMakeRange(0, phone.length)]; 
      [phone replaceOccurrencesOfString:@")" withString:@"" options:0 range:NSMakeRange(0, phone.length)]; 
      [phone replaceOccurrencesOfString:@"+336" withString:@"06" options:0 range:NSMakeRange(0, phone.length)]; 

      if (j == 0)  person.mainNumber = phone; 
      else if (j==1) person.secondNumber = phone; 
     } 
     CFRelease(phones); 

     // add the `Person` record 

     [self.tableData addObject:person]; 

     // add the ID for this person (and all linked contacts) to our set of `foundIDs` 

     NSArray *linkedPeople = CFBridgingRelease(ABPersonCopyArrayOfAllLinkedPeople(contactPerson)); 
     if (linkedPeople) { 
      for (id record in linkedPeople) { 
       [foundIDs addObject:@(ABRecordGetRecordID((__bridge ABRecordRef)record))]; 
      } 
     } else { 
      [foundIDs addObject:@(recordId)]; 
     } 
    } 
} 

CFRelease(addressBook); 

NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"fullName" ascending:YES]; 
[self.tableData sortUsingDescriptors:@[descriptor]]; 

Сказав это, вы, вероятно, должны перебирать все связанные контакты и искать там номера телефонов. Возможно, сделайте некоторую проверку имен тоже (например, если у вас есть одна запись для Дж. Д. Сэлинджера, а другая для Джона Дэвида Сэлинджера, есть алгоритм для определения того, какое имя вы хотите использовать). Ты можешь многое сделать. Но приведенное выше иллюстрирует минималистичное решение, которое добавляет контакт и любые связанные контакты в список найденных контактов.

+0

Большое вам спасибо! Вы спасете мою жизнь, и я могу все понять с вашими комментариями! – Viny76