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"];
}
}
Related
For some reason, a few of my contacts are missing from my tableView. I believe am I fetching all the necessary keys and have reviewed Apple's documentation, but am still stuck. Below is my code:
-(void)fetchContactsandAuthorization {
// Request authorization to Contacts
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 *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error)
{
NSLog(#"error fetching contacts %#", error);
}
else
{
NSString *phone;
NSString *fullName;
NSString *firstName;
NSString *lastName;
UIImage *profileImage;
NSMutableArray *contactNumbersArray = [[NSMutableArray alloc]init];
for (CNContact *contact in cnContacts) {
// copy data to my custom Contacts class.
firstName = contact.givenName;
lastName = contact.familyName;
if (lastName == nil) {
fullName=[NSString stringWithFormat:#"%#",firstName];
}else if (firstName == nil){
fullName=[NSString stringWithFormat:#"%#",lastName];
}
else{
fullName=[NSString stringWithFormat:#"%# %#",firstName,lastName];
}
UIImage *image = [UIImage imageWithData:contact.imageData];
if (image != nil) {
profileImage = image;
}else{
profileImage = [UIImage imageNamed:#"person-icon.png"];
}
NSString *number = contact.phoneNumbers.firstObject.value.stringValue;
if (number == (NSString *)NSNull.null || number == nil) {
[contactNumbersArray addObject:#"NO NUMBER"];
} else {
[contactNumbersArray addObject:number];
}
arrayPhoneData = contactNumbersArray;
NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,#"fullName",profileImage,#"userImage",phone,#"PhoneNumbers", nil];
[arrayTableData addObject:[NSString stringWithFormat:#"%#",[personDict objectForKey:#"fullName"]]];
}
dispatch_async(dispatch_get_main_queue(), ^{
//[tableViewContactData reloadData];
[self.tableView reloadData];
});
}
}
}];
}
Any help is much appreciated!!!!
`
let keys = [CNContactGivenNameKey, CNContactPhoneNumbersKey] as [Any]
do {
let contactStore = AppDelegate.getAppDelegate().contactStore
try contactStore.enumerateContacts(with: CNContactFetchRequest(keysToFetch: keys as! [CNKeyDescriptor])) { (contact, pointer) -> Void in
if !contact.phoneNumbers.isEmpty {
contacts.append(contact)
}
}
}
catch let error as NSError {
print(error.description, separator: "", terminator: "\n")
}
let contactPickerViewController = CNContactPickerViewController()
contactPickerViewController.delegate = self
present(contactPickerViewController, animated: true, completion: nil)
`
stick this in your app delegate
var contactStore = CNContactStore()
class func getAppDelegate() -> AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
Try double checking your predicate. I have had trouble with the predicate restricting the contacts I have been searching for and removed it entirely in the past. Not also that but you could try adding more keys to your contact keys. You're potentially restricting your search with keysToFetch.
You should access the Contact Book differently.
dispatch_async(dispatch_get_main_queue(), ^{
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == NO) {
//show access denied popup
return ;
}
NSError* contactError;
CNContactStore* addressBook = [[CNContactStore alloc]init];
[addressBook containersMatchingPredicate:[CNContainer predicateForContainersWithIdentifiers: #[addressBook.defaultContainerIdentifier]] error:&contactError];
NSArray *keysToFetch = #[CNContactMiddleNameKey,CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey,CNContactEmailAddressesKey];
CNContactFetchRequest * request = [[CNContactFetchRequest alloc]initWithKeysToFetch:keysToFetch];
[addressBook enumerateContactsWithFetchRequest:request error:&contactError usingBlock:^(CNContact * __nonnull contact, BOOL * __nonnull stop){\
NSString *firstName = contact.givenName;
NSString *lastName = contact.familyName;
//recommend to use a function like this one: [self parseContactWithContact:contact];
}];
}];
});
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
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?
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.
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.