I'm trying to manage the contacts of my app by creating a group.
Creating/Deleting a group works fine on simulator (with iOS 11.3 and with iOS 9.3).
In both cases, the default contact settings are set to iCloud in the iOS settings.
I have checked privacy settings in both cases, the permission to access the device contacts was set to YES
The following code fails on iPad with iOS 9.3.5.
-(void) createNewGroup:(NSString*)groupName
{
CFErrorRef error = NULL;
ABAddressBookRef ab = ABAddressBookCreateWithOptions(NULL, &error);
if (ab) {
ABRecordRef newGroup = ABGroupCreate();
ABRecordSetValue(newGroup, kABGroupNameProperty,(__bridge CFTypeRef)(groupName), nil);
ABAddressBookAddRecord(ab, newGroup, &error);
if (error) {
DDLogDebug(#"cannot create group -%#",error);
}else{
ABAddressBookSave(ab, &error);
}
if (error) {
DDLogDebug(#"cannot save group -%#",error);
}
//!!! important - save groupID for later use
self.groupId = ABRecordGetRecordID(newGroup); //-1 for iPad, and for other cases 2,3,4 ....
DDLogDebug(#"createNewGroup : %i",self.groupId );
CFRelease(newGroup);
CFRelease(ab);
}
}
and to delete the group:
Note: I did not test this method on iPad as there is no group that I want to delete, I will test this after I'm able to create a group on the iPad. This method worked as expected on simulator.
-(BOOL)deleteGroup:(NSString *)groupName{
BOOL res;
CFErrorRef error;
ABAddressBookRef ab = ABAddressBookCreate();
NSArray *groups = (__bridge NSArray *) ABAddressBookCopyArrayOfAllGroups(ab);
for (id _group in groups)
{
NSString *currentGroupName = (__bridge NSString*) ABRecordCopyValue((__bridge ABRecordRef)(_group), kABGroupNameProperty);
DDLogDebug(#"group name -%#",currentGroupName);
if ([groupName isEqualToString:currentGroupName])
{
res = ABAddressBookRemoveRecord(ab, (__bridge ABRecordRef)(_group), &error);
return res;
}
}
return NO;
}
I do not get any error but I get the groupID as -1 when trying to create group on iPad, and I check that group isn't created at all.
Related
I am trying to create a contact group in native by using following code, The Scenario i am trying is : Add any outlook account in native mail then enable contact sync, this will create a contact group. After this if i am trying to create a group from my App then its failing ..
ABAddressBookRef addressBook = ABAddressBookCreate();
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (granted) {
CFErrorRef error = NULL;
ABRecordRef worxMailGroup = ABGroupCreate();
BOOL success = ABRecordSetValue(worxMailGroup,kABGroupNameProperty,(__bridge CFTypeRef) #"TestGroup2",&error);
if (success) {
bool bStatus = ABAddressBookAddRecord(addressBook, worxMailGroup, &error);
if (bStatus) {
bStatus = ABAddressBookSave(addressBook, &error);
// bStatus is false and error also nil ..
}
}
}
});
});
Thanks
No matter what I try, iOS is telling me that I have 0 groups. I've tried both the ABGroup and CNGroup API. Nada. If I go into the Contacts app on my iPad and click on Groups, I see it listing five different groups (as expected). But both [CNContactStore groupsMatchingPredicate:error:] and ABAddressBookCopyArrayOfAllGroups() are giving me 0 element arrays back.
Here is my code for each:
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES) {
NSError *error;
NSArray *cnGroups = [store groupsMatchingPredicate:nil error:&error];
for( CNGroup *group in cnGroups ) {
AWLogInfo(#"JMS CN Group: %#", group.name);
}
}
}];
CFArrayRef allGroups = ABAddressBookCopyArrayOfAllGroups(addressBook);
for( int iGroup = 0; iGroup < CFArrayGetCount(allGroups); iGroup++ ) {
ABRecordRef groupRef = CFArrayGetValueAtIndex(allGroups, iGroup);
NSString *groupName = (__bridge_transfer NSString*)ABRecordCopyValue(groupRef, kABGroupNameProperty);
AWLogInfo(#"JMS Group %ld: %#", (long) iGroup, groupName);
}
(Note that I don't request AddressBook permission, because that's already being done elsewhere in my app. I am able to access contacts just fine -- in fact, right after this code snippet is some code that iterates through all of the contact records and it is no problem.)
What gives? What am I missing?
Edit: Note that I can see groups I create, I just can't see the groups created by other apps. I can see the contacts within those groups, but not the groups themselves. Is this expected behavior?
I was confusing groups with sources. If you list all sources, you'll get the stuff created by other apps.
That said, iOS seems to be pretty lousy about giving you a useful name for a source, so this still isn't really doing what I want.
In my app i am getting contact information directly buy doing this ...
ABAddressBookRef m_addressbook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(m_addressbook);
CFIndex nPeople = ABAddressBookGetPersonCount(m_addressbook);
for (int i=0;i < nPeople;i++)
{
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);
CFStringRef company,firstName,lastName;
firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
company = ABRecordCopyValue(ref, kABPersonOrganizationProperty);
}
So, i need to check first Whether this is ON/OFF Settings --> Privacy --> Contacts ON/OFF for my app.
For this I am doing this :
__block BOOL accessGranted = NO;
float sysver = [[[UIDevice currentDevice]systemVersion]floatValue];
if(sysver>=6) {
ABAddressBookRef addressBook = ABAddressBookCreate();
if (ABAddressBookRequestAccessWithCompletion != NULL) {
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 {
accessGranted = YES;
}
} else {
accessGranted = YES;
}
if(accessGranted)
{
// doing my stuff and moving on
} else {
// please make Settings --> Privacy --> Contacts my app. ON for accessing contacts.
}
My issues is , at very first time after installing app on device , app asked me to "Don't allow"/ "Ok" alert for contact grant access. I clicked on Ok but Settings --> Privacy --> Contacts for my app was OFF so again got alert to make it ON, "Settings" "Ok" so selected Settings , and i made it ON ,, once i made it ON app get SIGKILL nothing to console.
and later whenever i changed Privacy setting to OFF to ON app getting crash at background . i get SIGKILL nothing to console.
Thanks In Advance.
There is another post with a similar issue found here.
It is intended OS functionality that each application is terminated when Privacy settings are changed. This is to ensure that each application abides by the users privacy and doesn't continue to use any cached data after the privacy settings are altered.
Also please note that your suggested code
float sysver = [[[UIDevice currentDevice]systemVersion]floatValue];
if(sysver>=6) {
is not recommended by Apple and there is a better, more official approach such as using the Foundation #define values i.e.
BOOL isiOS6OrMoreRecent = NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_6_0 ? YES : NO;
However it is very bad practice to use iOS versions in order to determine available functionality, instead check for the feature itself independently of the OS version (Address Book Code here, such as:
if (ABAddressBookRequestAccessWithCompletion) { // if in iOS 6
// Request authorization to Address Book
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
Hello everyone I am trying to update a contact's phone using the following code
ABAddressBookRef addressBook = ABAddressBookCreate();
CFErrorRef error = nil;
ABMutableMultiValueRef phoneMultiValue = ABMultiValueCreateMutable(kABPersonPhoneProperty);
bool didAddphone = ABMultiValueAddValueAndLabel(phoneMultiValue, (CFTypeRef)(_homePhoneText.text), kABHomeLabel, NULL);
if(didAddphone){
ABRecordSetValue(ABAddressBookGetPersonWithRecordID(addressBook, [_ID integerValue]),
kABPersonPhoneProperty,
phoneMultiValue,
nil);
} else {
NSLog(#"Error adding email: %#", error);
error = nil;
}
But its not working. Any help ?
First off: ABAddressBookCreate is deprecated and will not work under iOS 6 (it always returns NULL). Instead use ABAddressBookCreateWithOptions (documentation: http://developer.apple.com/library/ios/#documentation/AddressBook/Reference/ABAddressBookRef_iPhoneOS/Reference/reference.html ).
After that, you need to save the address book to make the changes stick around, do that by calling ABAddressBookSave with your address book.
I have the following code:
NSMutableArray *contacts = [[NSMutableArray alloc]init];
CFErrorRef *error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
if (error)
}
NSArray *arrayOfPeople = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);
It works on the simulator and gives me the expected results - however on the device the number of contacts is 0 and there is no error (the app strangely does not ask me for permissions to access the address book - I even deleted and reinstalled the app)
Any Ideas ?
Thanks in advance
On ios 6 you need get access to the Address Book.
Call ABAddressBookRequestAccessWithCompletion() to get the permission.
see this and AddressHelper
CFErrorRef error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if (error) {
NSLog(#"error %#", error);
}else if (granted){
// Do what you want with the Address Book
}else{
NSLog(#"permission denied");
}
CFRelease(addressBook);
});