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];
}];
}];
});
Related
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"];
}
}
I am accessing contact from user phone. Everything is working perfectly but when I add it into the NSMutableArray then nothing is entered. In breakpoint when I click on array its showing 0X16bed870. My code is as follow.
-(void)mycontact
{
NSMutableArray * contactNumbersArray = [[NSMutableArray alloc] init];
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status == CNAuthorizationStatusDenied || status == CNAuthorizationStatusRestricted)
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:#"This app previously was refused permissions to contacts; Please go to settings and grant permission to this app so it can use contacts" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:TRUE completion:nil];
return;
}
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;
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"];
}
for (CNLabeledValue *label in contact.phoneNumbers) {
phone = [label.value stringValue];
if ([phone length] > 0) {
[contactNumbersArray addObject:phone];
}
}
NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,#"fullName",profileImage,#"userImage",phone,#"PhoneNumbers", nil];
}
dispatch_async(dispatch_get_main_queue(), ^{
for(int j=0;j<[contactNumbersArray count];j++)
{
NSString *newString = [[contactNumbersArray[j] componentsSeparatedByCharactersInSet:
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
componentsJoinedByString:#""];
contactNumbersArray[j]=newString;
}
});
}
}
}];
}
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?
Hi I am very new to ios and in my app I am using NSUrlSession for integrating services.
Here my main problem is when I get a response from the server, I can't handle them properly.
When I get a correct response, then see the below json stucture:-
responseObject = {
{
Name = Broad;
DeptNo = A00;
BatchNo = 23;
DeptId = 120;
},
{
Name = James;
DeptNo = B00;
BatchNo = 23;
DeptId = 123;
},
}
when I get a wrong response, see the below json stucture:-
responseObject = {
error = 1;
message = "Invalid Code";
}
when I get a correct response from the server, I am getting an exception in my below if block(like __NSCFArray objectForKey:]: unrecognized selector sent to instance 0x1611c200') and when I get a wrong response then T get exception in my else block
Please help me how to handle them
my code:-
(void) GetCallService1: (id)MainResponse{
dispatch_async(dispatch_get_main_queue(), ^{
NameArray = [[NSMutableArray alloc]init];
IdArray = [[NSMutableArray alloc]init];
if([MainResponse objectForKey:#"error"] != nil)
{
NSLog(#"No data available");
}
else{
for (NSDictionary *obj in MainResponse) {
if([obj objectForKey:#"Name"] && [obj objectForKey:#"DeptNo"]) {
NSString * Name = [obj objectForKey:#"Name"];
[NameArray addObject:Name];
NSString * Id = [obj objectForKey:#"id"];
[IdArray addObject:Id];
}
}
}
});
}
1)Change Your implementation like below
2)I checked is it dictionary type & error key has some value
3)Earlier you were calling objectForKey on Array, therefore it was crashing
-(void) GetCallService1: (id)MainResponse{
dispatch_async(dispatch_get_main_queue(), ^{
NameArray = [[NSMutableArray alloc]init];
IdArray = [[NSMutableArray alloc]init];
//here I checked is it dictionary type & error key has some value
if ([MainResponse isKindOfClass:[NSDictionary class ]] &&[MainResponse objectForKey:#"error"])
{
NSLog(#"No data available");
}
else{
for (NSDictionary *obj in MainResponse) {
if([obj objectForKey:#"Name"] && [obj objectForKey:#"DeptNo"]) {
NSString * Name = [obj objectForKey:#"Name"];
[NameArray addObject:Name];
NSString * Id = [obj objectForKey:#"id"];
[IdArray addObject:Id];
}
}
}
});
}
Try this:
//Result Block
typedef void (^ResultBlock)(id, NSError*);
//URL request
-(void)requestURL:(NSURLRequest *)request withResult:(ResultBlock)resultHandler{
//URLSession
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * data, NSURLResponse * response, NSError * error) {
if(!error){
NSError *jsonError = nil;
id result = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if([result isKindOfClass:[NSArray class]]){
//Success
resultHandler(result,nil);
}
else if([result isKindOfClass:[NSDictionary class]]){
if([[result objectForKey:#"error"] integerValue]){
//Failure.
NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
[errorDetail setValue:[result objectForKey:#"message"] forKey:NSLocalizedDescriptionKey];
NSError *error = [NSError errorWithDomain:#"Error" code:100 userInfo:errorDetail];
resultHandler(nil, errorDetail);
}
}
}
}];
[task resume];
}
//Call your requestURL method:
[self requestURL:request withResult:^(id result, NSError *error){
if(!error){
//Success, Read & update your list
}
else{
//Error
// NSLog(error.localizedDescription());
}
}];