Demander l'accès aux contacts par programme

109

Depuis la mise à jour vers iOS 6, j'ai remarqué que mon code pour ajouter un contact au carnet d'adresses de l'iPhone ne fonctionne plus. Je pense qu'il s'agit d'un problème lié à l'autorisation, car Apple nécessite désormais l'autorisation de l'utilisateur avant d'accéder aux contacts (résolution de ce problème).

Je m'attendais à ce que l'application demande automatiquement l'autorisation d'accéder aux contacts, comme dans la capture d'écran ci-dessous, mais ce n'est pas le cas. Essayer d'ajouter le contact échoue simplement avec ABAddressBookErrorDomain error 1.

Dois-je lancer par programme la boîte de dialogue de demande d'accès aux contacts? Comment cela se fait-il?

accéder aux contacts

Kyle Clegg
la source

Réponses:

180

Conformément à cette documentation sur le site d'Apple (faites défiler jusqu'à Confidentialité au milieu de la page), l'accès au carnet d'adresses doit être accordé avant de pouvoir y accéder par programme. Voici ce que j'ai fini par faire.

  #import <AddressBookUI/AddressBookUI.h>

  // Request authorization to Address Book
  ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);

  if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
    ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
      if (granted) {
          // First time access has been granted, add the contact
          [self _addContactToAddressBook];
      } else {
          // User denied access
          // Display an alert telling user the contact could not be added
      }
    });
  }
  else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
    // The user has previously given access, add the contact
    [self _addContactToAddressBook];
  }
  else {
    // The user has previously denied access
    // Send an alert telling user to change privacy setting in settings app
  }

Mise à jour pour iOS 9 et versions ultérieures:

Sur le site Web d'Apple:

Important

La structure de l'interface utilisateur du carnet d'adresses est obsolète dans iOS 9. Utilisez plutôt les API définies dans la structure ContactsUI. Pour en savoir plus, voir ContactsUI

Kyle Clegg
la source
J'ai modifié ma réponse pour inclure l'importation. Notez que vous devez également lier les frameworks AddressBook et AddressBookUI à votre projet dans l'onglet Build Phases.
Kyle Clegg
Je vérifierais également le grantedparamètre dans le bloc d'achèvement.
cheesus
Je pense qu'il pourrait y avoir un bogue dans ce code. Si j'arrière-plan de mon application, allez dans paramètres-> confidentialité-> contacts et activez / désactivez l'autorisation de mes applications, mon application se bloque immédiatement. Quelque chose doit-il être publié? (
Je
3
EDIT: Ce n'est pas un bug, c'est en fait une chose délibérée par le système d'exploitation ... stackoverflow.com/questions/12810638/…
AlBeebe
Merci d'avoir découvert cela. J'ai également remarqué ce comportement, mais je ne m'étais pas encore remis à regarder ce domaine de ce projet. L '«approche marteau» d'Apple est en effet intéressante.
Kyle Clegg
47

Cela a fait le tour parfait pour moi!

Sur iOS6, Apple introduit un nouveau contrôle de la confidentialité, l'utilisateur peut contrôler l'accès aux contacts et au calendrier par chaque application. Donc, du côté du code, vous devez ajouter un moyen de demander l'autorisation. Sous iOS5 ou avant, nous pouvons toujours appeler

ABAddressBookRef addressBook = ABAddressBookCreate();

pour obtenir le carnet d'adresses sans aucun problème, mais sous iOS6, si vous n'avez pas la permission, cet appel renverra simplement un pointeur vide. C'est pourquoi nous devons changer la méthode pour obtenir ABAddressBookRef.

__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);
    dispatch_release(sema);   
}
else { // we're on iOS 5 or older
    accessGranted = YES;
}

if (accessGranted) {
    // Do whatever you want here.
}

Dans le code, le sémaphore est utilisé pour bloquer jusqu'à la réponse, tandis qu'ABAddressBookRequestAccessWithCompletion demandera l'autorisation si l'application ne l'a pas demandé auparavant. Sinon, il suivra simplement les paramètres dans Paramètres-Confidentialité-Contact.

SOURCE: http://programmerjoe.blogspot.com/2012/10/ios6-permissions-contacts.html

yunas
la source
Merci Yunas, faire la if (ABAddressBookRequestAccessWithCompletion != NULL)vérification, pour contrôler s'il faut entrer dans la ABAddressBookGetAuthorizationStatus()section du code de Kyle a bien fonctionné pour moi avec iOS 5 et 6.
Ted
2
@Yunas Mais cela arrête tous les threads, je veux dire lorsque l'alerte apparaît demandant à l'utilisateur d'accéder à ses contacts, les boutons ne répondent pas, mon application raccroche, je crois que c'est à cause de GCD dispatch_semaphore_wait
Eshwar Chaitanya
eu des problèmes avec votre code dans Xcode5. Soveld et posté la mise à jour ci-dessous . cheers
jerik
6

Pour le cadre de contacts:

- (void)checkPermissionForCNContacts
{
    switch ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts])
    {
        case CNAuthorizationStatusNotDetermined:
        {
            [[[CNContactStore alloc] init] requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
                if (granted == YES)
                    [self showCNContactPicker];
            }];
        }
            break;
        case CNAuthorizationStatusRestricted:
        case CNAuthorizationStatusDenied:
                // Show custom alert
            break;
        case CNAuthorizationStatusAuthorized:
            [self showCNContactPicker];
            break;
    }
}
Zaraki
la source
3
ABAddressBookRef addressBook = ABAddressBookCreate();

__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);
    dispatch_release(sema);
}
else { // we're on iOS 5 or older
    accessGranted = YES;
}

if (accessGranted) {
    if(self.isContactsChanged)
    {
        {
            self.isContactsChanged=NO;
            CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
             ABAddressBookRegisterExternalChangeCallback(addressBook, addressBookChanged, self);

            int allPeopleCount = CFArrayGetCount(allPeople);

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

            __block int noNumberCount=1;
            managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
            newMoc = [[NSManagedObjectContext alloc] init];
            [newMoc setPersistentStoreCoordinator:[[AppDelegate getAppDelegate] persistentStoreCoordinator]];
            [self DeleteAllPhoneContact];
            NSNotificationCenter *notify = [NSNotificationCenter defaultCenter];
            [notify addObserver:self
                       selector:@selector(mergeChanges:)
                           name:NSManagedObjectContextDidSaveNotification
                         object:newMoc];
            self.backgroundQueue = dispatch_queue_create("com.storephonecontacts.bgqueue", NULL);
            __block NSMutableDictionary *dic;
            __block NSString *strTime,*strName,*strMobile,*strEmail,*strNotes;
            __block NSDate *nsDate;
            dispatch_async(self.backgroundQueue, ^{

                NSMutableDictionary *dict =nil;
                for (int i = 0; i < allPeopleCount; i++)
                {

                    dic = [[NSMutableDictionary alloc]init];
                    ABRecordRef record = CFArrayGetValueAtIndex(allPeople,i);
                    NSDate *date = (NSDate*)ABRecordCopyValue(record, kABPersonCreationDateProperty);
                    nsDate = [date retain];

                    NSDateFormatter *formatterTime = [[NSDateFormatter alloc] init];
                    [formatterTime setDateFormat:@"hh.mm"];
                    NSString    *dateStrPhone = [formatterTime stringFromDate:date];
                    strTime = [dateStrPhone retain];
                    [formatterTime release];

                    NSString *name = (NSString*)ABRecordCopyValue(record, kABPersonFirstNameProperty);
                    if([name length]>0)
                        name = [name stringByAppendingString:@" "];
                    NSString *name1 = (NSString*)ABRecordCopyValue(record, kABPersonLastNameProperty);
                    if([name1 length]>0)
                    {
                        if([name length]>0)
                            name = [name stringByAppendingString:name1];
                        else
                            name = (NSString*)ABRecordCopyValue(record, kABPersonLastNameProperty);
                    }
                    if([name length]>0)
                        strName = [name retain];
                    else
                        strName = [@"noName" retain];

                    //to save notes
                    NSString *notes = (NSString*)ABRecordCopyValue(record, kABPersonNoteProperty);
                    if(notes == NULL){
                        strNotes = @"noNotes";
                    }
                    else{
                        strNotes = [notes retain];
                    }
                    //for image
                    if (!ABPersonHasImageData(record)){

                    }
                    else{
                        CFDataRef imageData = ABPersonCopyImageData(record);
                        UIImage *image = [UIImage imageWithData:(NSData *) imageData];
                        [dic setObject:image forKey:@"image"];
                        CFRelease(imageData);
                    }
                    //To set Mobile
                    NSMutableArray* mobileArray = [[NSMutableArray alloc] init];
                    ABMutableMultiValueRef multi = ABRecordCopyValue(record, kABPersonPhoneProperty);
                    if (ABMultiValueGetCount(multi) > 0) {
                        // collect all emails in array
                        for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) {

                            CFStringRef mobileRef = ABMultiValueCopyValueAtIndex(multi, i);
                            CFStringRef locLabel = ABMultiValueCopyLabelAtIndex(multi, i);
                            NSString *phoneLabel =(NSString*) ABAddressBookCopyLocalizedLabel(locLabel);

                            if([phoneLabel isEqualToString:@"mobile"])
                                [mobileArray addObject:(NSString *)mobileRef];
                            else if([phoneLabel isEqualToString:@"iPhone"])
                                [mobileArray addObject:(NSString *)mobileRef];
                            else if([phoneLabel isEqualToString:@"home"])
                                [mobileArray addObject:(NSString *)mobileRef];
                            else if([phoneLabel isEqualToString:@"work"])
                                [mobileArray addObject:(NSString *)mobileRef];
                            else if([phoneLabel isEqualToString:@"main"])
                                [mobileArray addObject:(NSString *)mobileRef];
                            else if([phoneLabel isEqualToString:@"other"])
                                [mobileArray addObject:(NSString *)mobileRef];
                            CFRelease(mobileRef);
                            CFRelease(locLabel);
                        }
                    }
                    CFRelease(multi);
                    if([mobileArray count]>0)
                        strMobile = [[mobileArray objectAtIndex:0]retain];
                    else{
                        NSString *str=[NSString stringWithFormat:@"noNumber%i",noNumberCount];
                        strMobile = [str retain];
                        noNumberCount++;
                    }
                    [mobileArray release];

                    //To set E-mail
                    NSMutableArray* emailArray = [[NSMutableArray alloc] init];
                    multi = ABRecordCopyValue(record, kABPersonEmailProperty);
                    if (ABMultiValueGetCount(multi) > 0) {
                        // collect all emails in array
                        for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) {
                            CFStringRef emailRef = ABMultiValueCopyValueAtIndex(multi, i);
                            [emailArray addObject:(NSString *)emailRef];
                            CFRelease(emailRef);
                        }
                    }

                    CFRelease(multi);
                    if([emailArray count]>0)
                        strEmail = [[emailArray objectAtIndex:0]retain];
                    else
                        strEmail = [@"noemail" retain];
                    [emailArray release];

                    bool addBool = NO;

                    if([strName isEqualToString:@"noName"]){
                        if([strEmail isEqualToString:@"noemail"]){

                        }
                        else{
                            [dic setObject:strEmail forKey:@"name"];
                            addBool = YES;
                        }

                        if(addBool == NO){
                            if([strMobile isEqualToString:@"noNumber"]){

                            }
                            else{
                                [dic setObject:strMobile forKey:@"name"];
                                addBool = YES;
                            }
                        }
                    }
                    else{
                        [dic setObject:strName forKey:@"name"];
                        addBool = YES;
                    }
                    [dic setObject:strEmail forKey:@"email"];
                    [dic setObject:strMobile forKey:@"mobile"];
                    [dic setObject:nsDate forKey:@"date"];
                    [dic setObject:strTime forKey:@"time"];
                    [dic setObject:strNotes forKey:@"notes"];

                    if(addBool == YES)
                        [contactArrTemp addObject:dic];

                    if([strMobile hasPrefix:@"0"]){
                        NSString *contactNumber=[strMobile stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:@""];
                        if(contactNumber.length>7)
                            [dic setObject:@"iPhone" forKey:@"ContactType"];

                    }
                    else {
                        if(strMobile.length>9)
                            [dic setObject:@"iPhone" forKey:@"ContactType"];

                    }
                    if(![[dic objectForKey:@"ContactType"] isKindOfClass:[NSNull class]] && [dic objectForKey:@"ContactType"])
                    {
                        [self InsertContactWithContactInfoDictionary:dic];
                    }
                    [strName release];
                    [nsDate release];
                    [strEmail release];
                    [strMobile release];
                    [strTime release];
                    [strNotes release];
                    [dic release];
                }
                dispatch_async(self.backgroundQueue, ^(void){ [self gcdDidFinishaddfebriteParsing:dict]; });
                dispatch_release(self.backgroundQueue);
                self.backgroundQueue=nil;
            });

        }
    }
    else
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"PhoneContactsSaved" object:nil userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:@"Successful"]];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"updateContacts" object:nil userInfo:[NSDictionary dictionaryWithObject:@"success" forKey:@"update"]];
    }
}
Ritesh verma
la source
7
Ajoutez peut-être du texte pour répondre aux questions.
user905686
3

On a eu quelques problèmes avec Yunas code sur iOS6.1 dans Xcode5. Avec quelques petites adaptations, cela a fonctionné pour moi.

Le problème était que ARC dans iOS 6, ne permet pas dispatch_release(sema);Voici le code de travail. Remarque: j'utilise m_addressbookau lieu de addressbookcomme ABAddressBookRef!

ViewController.m

#import "ViewController.h"
#import <AddressBook/AddressBook.h>
#import <AddressBook/ABAddressBook.h>
#import <AddressBook/ABPerson.h>

@interface ViewController ()

@property (nonatomic, strong) NSMutableArray* contactList;

@end

@implementation ViewController

- (void)viewDidLoad
{
  [super viewDidLoad];

  ABAddressBookRef m_addressbook =  ABAddressBookCreateWithOptions(NULL, NULL);

  __block BOOL accessGranted = NO;
  if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
      dispatch_semaphore_t sema = dispatch_semaphore_create(0);
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
          @autoreleasepool {
              // Write your code here...
              // Fetch data from SQLite DB
          }
      });

      ABAddressBookRequestAccessWithCompletion(m_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) {
  // do your stuff
  }
}

// ...
Jerik
la source
Seul l'écran noir apparaît comme si l'application est gelée et lorsque je ferme l'application, je vois une alerte d'autorisation. Avez-vous une idée de la raison pour laquelle cela se produit? cette alerte doit être sur l'application et non sous un écran noir.
Yucel Bayram
2
- (void)viewDidLoad
{
    [super viewDidLoad];


    [self loadPhoneContacts];
}



-(void)loadPhoneContacts{

    ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();

    if (status == kABAuthorizationStatusDenied) {
        // if you got here, user had previously denied/revoked permission for your
        // app to access the contacts, and all you can do is handle this gracefully,
        // perhaps telling the user that they have to go to settings to grant access
        // to contacts

        [[[UIAlertView alloc] initWithTitle:nil message:@"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
        return;
    }

    CFErrorRef error = NULL;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);

    if (error) {
        NSLog(@"ABAddressBookCreateWithOptions error: %@", CFBridgingRelease(error));
        if (addressBook) CFRelease(addressBook);
        return;
    }

    if (status == kABAuthorizationStatusNotDetermined) {

        // present the user the UI that requests permission to contacts ...

        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
            if (error) {
                NSLog(@"ABAddressBookRequestAccessWithCompletion error: %@", CFBridgingRelease(error));
            }

            if (granted) {
                // if they gave you permission, then just carry on

                [self listPeopleInAddressBook:addressBook];
            } else {
                // however, if they didn't give you permission, handle it gracefully, for example...

                dispatch_async(dispatch_get_main_queue(), ^{
                    // BTW, this is not on the main thread, so dispatch UI updates back to the main queue

                    [[[UIAlertView alloc] initWithTitle:nil message:@"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
                });
            }

            if (addressBook) CFRelease(addressBook);
        });

    } else if (status == kABAuthorizationStatusAuthorized) {
        [self listPeopleInAddressBook:addressBook];
        if (addressBook) CFRelease(addressBook);
    }
}

- (void)listPeopleInAddressBook:(ABAddressBookRef)addressBook
{
    NSInteger numberOfPeople = ABAddressBookGetPersonCount(addressBook);
    NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));

    for (NSInteger i = 0; i < numberOfPeople; i++) {
        ABRecordRef person = (__bridge ABRecordRef)allPeople[i];

        NSString *firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
        NSString *lastName  = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
        NSLog(@"Name:%@ %@", firstName, lastName);

        ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);

        CFIndex numberOfPhoneNumbers = ABMultiValueGetCount(phoneNumbers);
        for (CFIndex i = 0; i < numberOfPhoneNumbers; i++) {
            NSString *phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phoneNumbers, i));
            NSLog(@"  phone:%@", phoneNumber);
        }

        CFRelease(phoneNumbers);

        NSLog(@"=============================================");
    }
}
Sandip Patel - SM
la source
1

Si quelqu'un a un problème avec le carnet d'adresses dans iOS5, utilisez

ABAddressBookRef addressBook = ABAddressBookCreate(); 

Au lieu de

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL,NULL);
Rajneesh071
la source
1
ABAddressBookRequestAccessWithCompletion(ABAddressBookCreateWithOptions(NULL, nil), ^(bool granted, CFErrorRef error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (!granted){
                    [[[UIAlertView alloc] initWithTitle:@"Contacts Access Denied"
                                                message:@"This app requires access to your device's Contacts.\n\nPlease enable Contacts access for this app in Settings / Privacy / Contacts"
                                               delegate:nil
                                      cancelButtonTitle:@"Dismiss"
                                      otherButtonTitles:nil] show];
            } else {
                //access authorized
            }
        });
    });

Pour ajouter une description à l'alerte, utilisez InfoPlist.strings.

NSContactsUsageDescription = "TESTING!";

jose920405
la source
1

Swift 3. N'oubliez pas d'importer les contacts

func requestForContactAccess(completionHandler: @escaping (_ accessGranted: Bool) -> Void) {
    let authorizationStatus = CNContactStore.authorizationStatus(for: CNEntityType.contacts)
    switch authorizationStatus {
    case .authorized:
        completionHandler(true)
    case .denied, .notDetermined:
        self.contactStore.requestAccess(for: CNEntityType.contacts, completionHandler: { (access, accessError) -> Void in
            if access {
                completionHandler(access)
            } else {
                if authorizationStatus == CNAuthorizationStatus.denied {
                    DispatchQueue.main.async(execute: { () -> Void in
                        let message = "\(accessError!.localizedDescription)\n\nPlease allow the app to access your contacts through the Settings."
                        self.showMessage(message: message)
                    })
                }
            }
        })
    default:
        completionHandler(false)
    }
}
Akhilendra Singh
la source
1

Selon la récente documentation de développement Apple iOS, Apple insiste pour utiliser Contact en plus du carnet d'adresses .

CNAuthorizationStatus authorizationStatus = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    switch (authorizationStatus) {
        case CNAuthorizationStatusNotDetermined: {

            break;
        }
        case CNAuthorizationStatusRestricted: {

            break;
        }
        case CNAuthorizationStatusDenied:{

            return;
        }
            break;
        case CNAuthorizationStatusAuthorized: {

            break;
        }
    }

Le code ci-dessus objectif c aide à trouver l'autorisation d'accès aux contacts météorologiques est accordée ou non.

Sk Borhan Uddin
la source
fonctionne comme un charme merci! .... juste un point de référence pour les développeurs juniors. vous devez aller dans .xcodeproj -> general -> Frameworks, Libraries, and Embedded Contents ... puis ajouter l'élément 'Contacts.framework' (et peut-être aussi 'ContactsUI.framework' si vous le souhaitez)
effet de serre
0

Avec iOS 6, vous devez demander une autorisation comme celle-ci

requestAccessToEntityType:EKEntityTypeEvent completion:
user1592698
la source
2
Votre suggestion fonctionne pour l'action EventKit. L'équivalent pour accéder au répertoire est ABAddressBookRequestAccessWithCompletion. Merci de m'avoir mis sur la bonne voie!
Kyle Clegg
L'un de vous peut-il donner à ABAddressBookRequestAccessWithCompletion la bonne réponse et l'accepter?
Brian
0

Pour obtenir le carnet d'adresses dans iOS

- (void)retreiveAllContacts
{
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);

CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);

if (!people) {
    return ;
}

CFMutableArrayRef peopleMutable = CFArrayCreateMutableCopy(kCFAllocatorDefault,
                                                           CFArrayGetCount(people),
                                                           people);

CFArraySortValues(peopleMutable,
                  CFRangeMake(0, CFArrayGetCount(peopleMutable)),
                  (CFComparatorFunction) ABPersonComparePeopleByName,
                  (void*) ABPersonGetSortOrdering());

NSMutableArray *contacts = [[NSMutableArray alloc] initWithCapacity:CFArrayGetCount(peopleMutable)];

for (CFIndex i = 0; i < CFArrayGetCount(peopleMutable); i++)
{

    ABRecordRef person = CFArrayGetValueAtIndex(peopleMutable, i);

    int32_t recId  =  ABRecordGetRecordID(person);

    NSString * abId = [NSString stringWithFormat:@"%d", recId];

    ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);

    ABMultiValueRef emailIds = ABRecordCopyValue(person, kABPersonEmailProperty);


    NSString* firstName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);

    NSString* lastName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);

    NSString* companyName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonOrganizationProperty);

    NSString* displayName = [firstName ? firstName : @"" stringByAppendingFormat:@" %@", lastName ? lastName : @""];

    displayName = [displayName stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" "]];


    NSMutableDictionary* contactInfo = [[NSMutableDictionary alloc] init];

    if(ABPersonHasImageData(person))
    {
        CFDataRef imageDataRef = ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail);

        NSData * imageData = (__bridge NSData *)imageDataRef;

        UIImage * thumbImage = [UIImage imageWithData:imageData];

        [contactInfo setObject:thumbImage forKey:@"picture"];
    }

    if(!firstName)
        firstName = @"";

    if (!lastName)
        lastName = @"";

    if(!displayName)
        displayName = @"";

    if(!companyName)
        companyName = @"";

   // [contactInfo setObject:[firstName capitalizedString] forKey:kFirstNameKey];

    //[contactInfo setObject:[lastName capitalizedString] forKey:kLastNameKey];

    [contactInfo setObject:[displayName capitalizedString] forKey:@"name"];

    [contactInfo setObject:abId forKey:@"ABID"];


  //  [contactInfo setObject:companyName forKey:kCompanyNameKey];

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

    for (CFIndex j=0; j < ABMultiValueGetCount(phoneNumbers); j++)
    {
        NSString* phone = (__bridge NSString*)ABMultiValueCopyValueAtIndex(phoneNumbers, j);

        CFStringRef localizedLabel = ABMultiValueCopyLabelAtIndex(phoneNumbers,j);

      //  NSString *phoneLabel =(__bridge NSString*) ABAddressBookCopyLocalizedLabel(localizedLabel);


        if( phone)
        {
            //                NSLog(@"validatedPhone: %@", validatedPhone);


            [phoneNumbersList addObject:phone];
        }

        if (localizedLabel) {
            //                            NSLog(@"localizedLabel: %@", localizedLabel);
            CFRelease(localizedLabel);
        }
    }

    if(phoneNumbers)
    {
        //                        NSLog(@"phoneNumbers: %@", phoneNumbers);

        CFRelease(phoneNumbers);

        //            NSLog(@"phoneNumbers Release: %@", phoneNumbers);

    }

    [contactInfo setObject:phoneNumbersList forKey:@"phoneNumbers"];

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

    for (CFIndex j=0; j < ABMultiValueGetCount(emailIds); j++)
    {
        NSString* email = (__bridge NSString*)ABMultiValueCopyValueAtIndex(emailIds, j);

        CFStringRef localizedLabel = ABMultiValueCopyLabelAtIndex(emailIds, j);


        if(email)
        {


            [emailList addObject:email];
        }

    }

    if(emailIds)
    {
        CFRelease(emailIds);

    }

    if(emailList && [emailList count])
        [contactInfo setObject:emailList forKey:@"emails"];

    if ([phoneNumbersList count] > 0 || [emailList count] > 0) {
        [contacts addObject:contactInfo];
    }
}

//CFRelease();
CFRelease(people);

if([contacts count])
{
    [self createiOSContactsDataSourceWithFeed:contacts];
}

}
Ramesh
la source
0

Ce code montre comment définir l'autorisation et comment obtenir tous les contacts du téléphone et afficher les contacts dans la liste avec l'étiquette d'étiquette

var contactStore = CNContactStore()
var contactArray = [CNContact]()

func getContacts()
{

    if CNContactStore.authorizationStatus(for: .contacts) == .notDetermined
    {

        contactStore.requestAccess(for: .contacts, completionHandler: { (authorized:Bool, error:Error?) in

            if authorized {



                let requestForContacts = CNContactFetchRequest(keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: CNContactFormatterStyle.fullName), CNContactPhoneNumbersKey as CNKeyDescriptor, CNContactImageDataKey as CNKeyDescriptor, CNContactNicknameKey as CNKeyDescriptor])
                do{
                    try self.contactStore.enumerateContacts(with: requestForContacts) { (contacts : CNContact, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
                        self.contactArray.append(contacts)
                        //print("hello")
                    }
                }
                catch {
                    print("EXCEPTION COUGHT")
                }
            }
        })
    }
    else if CNContactStore.authorizationStatus(for: .contacts) == .authorized
    {
        let requestForContacts = CNContactFetchRequest(keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: CNContactFormatterStyle.fullName), CNContactPhoneNumbersKey as CNKeyDescriptor, CNContactImageDataKey as CNKeyDescriptor, CNContactNicknameKey as CNKeyDescriptor])
        do{
            try self.contactStore.enumerateContacts(with: requestForContacts) { (contacts : CNContact, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
                self.contactArray.append(contacts)
            }
        }
        catch {

        }

    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    getContacts()

}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    //print(contactArray)
    return contactArray.count

}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "defaultCell")

    if cell != nil{

        //var dig = String()
        var hmdig = [String]()

        let names = contactArray[indexPath.row]
        print(names)

        let name1 = names.givenName+" "+names.middleName+" "+names.familyName

        for number in names.phoneNumbers
        {
            let phoneNumber = number.value

            let dig = (phoneNumber.value(forKey: "digits") as? String)!
            hmdig.append(dig)

        }

        // Set the contact image.
        if let imageData = names.imageData
        {
            let myImage = cell?.viewWithTag(30) as! UIImageView
            myImage.image = UIImage(data: imageData)
        }


//            let niknm = names.nickname

        let nameLable1 = cell?.viewWithTag(10) as! UILabel
                nameLable1.text = name1

        let nameLable2 = cell?.viewWithTag(20) as? UILabel

            nameLable2?.text = hmdig.joined(separator: ",\n")

//           let nameLable3 = cell?.viewWithTag(40) as? UILabel
//                nameLable3?.text = niknm


        return cell!

    }
    else{

        return UITableViewCell()
    }
}
Punit
la source