AddressBook api is deprecated in ios 9. I want to load all contacts in an array and display it in a UITableView. I don't want to use iOS default ContactPicker as I have to do some customization while displaying. How to load all contact list in an array for further use?
First I had to check the permission id it is not defined then ask for permission for accessing contacts. Like this:
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status == CNAuthorizationStatusNotDetermined) {
[self.contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError *error) {
if (granted) {
[self loadUserListFromPhoneBook];
}
}];
}
else if(status == CNAuthorizationStatusAuthorized) {
[self loadUserListFromPhoneBook];
}
After that I had to iterate through the contact list and load all contacts like this:
-(void) loadUserListFromPhoneBookFor
{
NSMutableArray *contacts = [NSMutableArray array];
NSError *error;
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:#[CNContactIdentifierKey, [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]]];
BOOL success = [self.contactStore enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact *contact, BOOL *stop) {
[contacts addObject:contact];
}];
if (!success) {
NSLog(#"error = %#", error);
}
CNContactFormatter *formatter = [[CNContactFormatter alloc] init];
for (CNContact *contact in contacts) {
NSString *string = [formatter stringFromContact:contact];
NSLog(#"contact = %#", string);
}
}
You can use necessary keys for getting more information. Have a look at this for more information. Its has all new contact classes. This video of WWDC helped a lot.
Related
We know that contacts in iOS can be synced from Google, iCloud and Phone. Well, we can fetch a bunch of Contacts using Contacts.framework, but I want to know which account it belongs to.
I mean, I need to differentiate Email and Phone synced contacts. Is there any way to do so?
I am using contact framework. I am getting identifier by using CNContainer, but how to get account name in which contacts are stored and also how fetch that contact’s from that account?
Can you please try fetching All container's and then you can Group those contacts according to the container name
-(void)fetchContacts
{
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES)
{
NSArray * contactContainerArray = [store containersMatchingPredicate:nil error:nil];
for(CNContainer * container in contactContainerArray) {
NSLog(#"Container name == %# ",container.name);
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:container.identifier];
NSError *error;
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error)
{
NSLog(#"error fetching contacts %#", error);
}
else
{
for (CNContact *contact in cnContacts) {
NSMutableArray *contactNumbersArray = [[NSMutableArray alloc]init];
// contact.givenName;
// contact.familyName;
for (CNLabeledValue *label in contact.phoneNumbers) {
// [label.value stringValue]; Phone Number
}
}
}
}
}
}];
}
We know that contacts in iOS can be synced from Google, iCloud and Phone. Well, we can fetch a bunch of Contacts using Contacts.framework, but I want to know which account it belongs to.
I mean, I need to differentiate Email and Phone synced contacts. Is there any way to do so?
I am using contact framework. I am getting identifier by using CNContainer, but how to get account name in which contacts are stored and also how fetch that contact’s from that account?
Can you please try fetching All container's and then you can Group those contacts according to the container name
-(void)fetchContacts
{
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES)
{
NSArray * contactContainerArray = [store containersMatchingPredicate:nil error:nil];
for(CNContainer * container in contactContainerArray) {
NSLog(#"Container name == %# ",container.name);
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:container.identifier];
NSError *error;
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error)
{
NSLog(#"error fetching contacts %#", error);
}
else
{
for (CNContact *contact in cnContacts) {
NSMutableArray *contactNumbersArray = [[NSMutableArray alloc]init];
// contact.givenName;
// contact.familyName;
for (CNLabeledValue *label in contact.phoneNumbers) {
// [label.value stringValue]; Phone Number
}
}
}
}
}
}];
}
How to display contact in table view?
I have fetched the contacts via CNContactStore iOS 9.
- (void) getContacts {
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES) {
//keys with fetching properties
NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey,CNContactImageDataKey];
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
NSArray *cnContactsarray = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error) {
NSLog(#"error fetching contacts %#", error);
}
else {
for (CNContact *contact in cnContactsarray) {
//store all the contacts as per your requirement
NSLog(#"Name : %#",contact.givenName);
NSLog(#"Id : %#",contact.identifier);//the contact id which you want
[_ContactsCN addObject:contact];
}
}
NSLog(#"array %#",_ContactsCN);
}
}];
}
Any help will be appreciated.
You need to reload data on main thread when your fetch contact from CNContact is complete
to run on main thread
dispatch_async(dispatch_get_main_queue(), ^{// reload your table here
});
I am using this code to export contact from ios phonebook to .vcf file. I have used this code for the task. But vcardString is always returning nil. Please help me to solve this issue.
NSMutableArray *contacts=[NSMutableArray alloc] init];
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!granted) {
dispatch_async(dispatch_get_main_queue(), ^{
});
return;
}
NSMutableArray *contacts = [NSMutableArray array];
NSError *fetchError;
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:#[CNContactIdentifierKey, [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]]];
BOOL success = [store enumerateContactsWithFetchRequest:request error:&fetchError usingBlock:^(CNContact *contact, BOOL *stop) {
[contacts addObject:contact];
}];
if (!success) {
NSLog(#"error = %#", fetchError);
}
// you can now do something with the list of contacts, for example, to show the names
CNContactFormatter *formatter = [[CNContactFormatter alloc] init];
for (CNContact *contact in contacts) {
[contactsArray addObject:contact];
// NSString *string = [formatter stringFromContact:contact];
//NSLog(#"contact = %#", string);
}
//NSError *error;
NSData *vcardString =[CNContactVCardSerialization dataWithContacts:contactsArray error:&error];
NSLog(#"vcardString = %#",vcardString);
}];
Change this line:
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:#[[CNContactVCardSerialization descriptorForRequiredKeys]]
This fetches all required info for creating a vCard.
How do I customize the UI of the CNContactPickerViewController?
I want to alter the colors, fonts, and text - similar to how snapchat has done?
Currently - my CNContactPickerViewController looks exactly like Apple's native contacts app.
First get contacts from address book and pass them into an NSArray:
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
NSMutableArray *contacts = [NSMutableArray array];
NSError *fetchError;
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:#[CNContactIdentifierKey, [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]]];
BOOL success = [store enumerateContactsWithFetchRequest:request error:&fetchError usingBlock:^(CNContact *contact, BOOL *stop) {
[contacts addObject:contact];
}];
if (!success) {
NSLog(#"error = %#", fetchError);
}
}];
Then simply use the NSArray in a UITableView and from there you can customize the font, colors, etc.