Not able to create vcard of contacts using contact framework - ios

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.

Related

On creating VCard not getting contact image and notes in iOS

Fetching contact list using CNContactStore and converting complete contact list to VCard, all are coming fine except i am not getting contact image and notes.
NSMutableArray *contactsArray=[[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:#[[CNContactVCardSerialization descriptorForRequiredKeys], [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]]];
BOOL success = [store enumerateContactsWithFetchRequest:request error:&fetchError usingBlock:^(CNContact *contact, BOOL *stop) {
[contacts addObject:contact];
}];
if (!success) {
NSLog(#"error = %#", fetchError);
}
for (CNContact *contact in contacts) {
CNContact *contact1 = contact.mutableCopy;
[contactsArray addObject:contact1];
}
NSData *vcardString =[CNContactVCardSerialization dataWithContacts:contactsArray error:&error];
vcardStr = [[NSString alloc] initWithData:vcardString encoding:NSUTF8StringEncoding];
NSLog(#"vcardStr = %#",vcardStr);
}];
Contact Profile images from CNContact
if (granted == YES) {
NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
NSArray *Contacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error)
{
//error
}
else
{
for (CNContact *contact in Contacts)
{
UIImage *contactProfileImage;
if (contact.imageDataAvailable)
{
UIImage * image = [UIImage imageWithData:contact.imageData];
contactProfileImage = image;
}
else
{
contactProfileImage = [UIImage imageNamed:#"icon.png"];
}
}

How to fetch Device contacts and how to show individually

i need to fetch all contacts from device and want to show individually accordingly ..kindly have a look my code thanks
// using method to fetch contacts from device
-(void)fetchContacts{
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if( status == CNAuthorizationStatusDenied || status == CNAuthorizationStatusRestricted){
NSLog(#"access denied");
}else{
CNContactStore *contactStore = [[CNContactStore alloc] init];
NSArray *keys = [[NSArray alloc]initWithObjects:CNContactIdentifierKey, CNContactEmailAddressesKey, CNContactBirthdayKey, CNContactImageDataKey, CNContactPhoneNumbersKey, CNContactViewController.descriptorForRequiredKeys, nil];
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
request.predicate = nil;
[contactStore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact* __nonnull contact, BOOL* __nonnull stop){
NSString *phoneNumber = #"";
if( contact.phoneNumbers)
phoneNumber = [[[contact.phoneNumbers firstObject] value] stringValue];
NSMutableDictionary *contactValue=[[NSMutableDictionary alloc] init];
if ([contact.givenName isEqualToString:#""]) {
}else{
[contactValue setValue:phoneNumber forKey:#"phoneNumber"];
[contactValue setObject:contact.givenName forKey:#"userName"];
[contactValue setObject:contact.familyName forKey:#"familyName"];
[contactValue setObject:[contact.emailAddresses valueForKey:#"value"] ?:#"" forKey:#"emailAddress"];
[contactValue setObject:contact.identifier forKey:#"phoneIdentifier"];
}
[_totalContact addObject:contactValue];
}];
}
You can use Contacts framework for that.
CNContactStore *cnContactStore = [[CNContactStore alloc] init];
[cnContactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES) {
NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
NSString *containerId = cnContactStore.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
_contactDetailArray = [cnContactStore unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error) {
NSLog(#”error fetching contacts %#”, error);
} else {
//Do Something
}
}
}];
For Complete code please visit my blog

iOS Objective-C: CNContactStore unifiedContactsMatchingPredicate is extremely slow on some cases. What could be the cause for the latency?

CNEntityType entityType = CNEntityTypeContacts;
NSMutableArray* allContacts = [[NSMutableArray alloc] init];
CNContactStore * contactStore = [[CNContactStore alloc] init];
NSArray *keys = #[CNContactFamilyNameKey, CNContactMiddleNameKey, CNContactGivenNameKey, CNContactOrganizationNameKey,
CNContactNicknameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
NSError *error;
if ([CNContactStore authorizationStatusForEntityType:entityType] == CNAuthorizationStatusNotDetermined)
{
[contactStore requestAccessForEntityType:entityType completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
NSArray* allContainers = [contactStore containersMatchingPredicate:nil error:&error];
for (CNContainer* container in allContainers)
{
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:container.identifier];
NSArray* cnContacts = [contactStore unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error) {
NSLog(#"error fetching contacts %#", error);
} else {
for (CNContact *contact in cnContacts) {
[allContacts addObject:contact];
}
}
}
}
}];
It seems on some phones the performance of unifiedContactsMatchingPredicate can be extremely slow while on others it is pretty fast. What may be the cause of the performance discrepancy? As far as I can tell the contacts on different phones aren't stored that differently, is there something else that could be the cause?

How to load all contacts in an array ios9

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.

Customize ContactPicker UI in iOS 9

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.

Resources