How i do update an existing contact phone number? - ios

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.

Related

Creating/Deleting an addressbook group fails in iPad device

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.

Sorting contacts based on recently used/most used/urgency in AddressBook iOS

I need to sort contacts in user's device based on recently used/most used/urgency and display them in a single view(not as in the phone app where these are displayed in separate tabs). I have researched about this but only got to know about sorting contacts alphabetically. Does the AddressBook framework allow this or is there some other way around? Any help would be appreciated.
No. Unfortunately, there is no way of knowing if a record has been recently used or not.
However, you can sort records in the address book using the properties specified below:
Here is a simple example of sorting records based on the creation date in descending order.
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(nil, NULL);
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBookRef));
NSArray *sortedPeople = [allPeople sortedArrayUsingComparator:^NSComparisonResult(id aRecord, id otherRecord) {
ABRecordRef aRecordRef = (__bridge ABRecordRef)aRecord;
ABRecordRef otherRecordRef = (__bridge ABRecordRef)otherRecord;
NSDate *aRecordCreationDate = CFBridgingRelease(ABRecordCopyValue(aRecordRef, kABPersonCreationDateProperty));
NSDate *otherRecordCreationDate = CFBridgingRelease(ABRecordCopyValue(otherRecordRef, kABPersonCreationDateProperty));
return [aRecordCreationDate compare:otherRecordCreationDate];
}];
});
CFRelease(addressBookRef);
Hi I have found a solution First we create Abaddressbook and register it with changes callback like this
1)ABAddressBookRef ntificationaddressbook = ABAddressBookCreate();
2)ABAddressBookRegisterExternalChangeCallback(ntificationaddressbook,addressBookChanged, self);
and when you will make a change in any contact (modified,open,edit etc).
then its callback will call its delegate like this
3)void addressBookChanged(ABAddressBookRef reference,
CFDictionaryRef dictionary,
void *context)
{
/// Address book is changed
// Now you can Implement logic
1-First of all get the change date and time which is now. from [NSdate date].
this will be the change date/time of a record
}
Hope it will help you.

iOS AddressBook Adding multiple people to a group

I am attempting to create a feature with my app that allows people to be easily added and/or removed from a group on iOS. The code below works perfectly if I:
1) add one person at a time
2) remove one person at a time
If however I select multiple people to add and/or remove simultaneously only the first action - first add if any or first remove if no additions - is committed to the address book. This method can be called over and over again with any one individual action and it will succeed. I cannot determine why I cannot get it to save multiple adds/deletes within the context of a single call to save. It should be pointed out that no error is giving and stepping through the code the booleans used to determine success indicate that everything worked perfectly.
I have attempted various combinations of adjusting code, for example: create a local address book, retrieve the groupRef, save the address book all within each of the for loops. I've also investigated reverting the address book after saving it to no avail. Thoughts or experiences?
-(IBAction)save:(id)sender
{
#synchronized(self)
{
CFErrorRef error = NULL;
BOOL success = NO;
BOOL successfulSave = NO;
ABAddressBookRef localAddressBook = ABAddressBookCreateWithOptions(NULL, &error);
group = ABAddressBookGetGroupWithRecordID(localAddressBook, groupID);
for (CFIndex addItemCount = 0; addItemCount < [theAddList count]; ++addItemCount)
{
NSNumber *addID = [theAddList objectAtIndex:addItemCount];
ABRecordRef thePersonID = ABAddressBookGetPersonWithRecordID(localAddressBook, [addID intValue]);
success = success || ABGroupAddMember(group, thePersonID, &error);
}
for (CFIndex removeItemCount = 0; removeItemCount < [theRemoveList count]; ++removeItemCount)
{
NSNumber *removeID = [theRemoveList objectAtIndex:removeItemCount];
ABRecordRef thePersonID = ABAddressBookGetPersonWithRecordID(localAddressBook, [removeID intValue]);
success = success || ABGroupRemoveMember(group, thePersonID, &error);
}
if (success)
{
successfulSave = ABAddressBookSave(localAddressBook, &error);
}
if (!(successfulSave && success))
{
UIAlertView *addressBookUpdateAlert = [[UIAlertView alloc] initWithTitle:#"AddressBook Error" message:#"An update to your address book could not be processed at this time. Try again shortly." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
// we can't update a GUI element from a background thread - appears sensitivity didn't appear until iOS 8
[[NSOperationQueue mainQueue] addOperationWithBlock:
^{
[addressBookUpdateAlert show];
}];
}
else
{
[[self navigationController] popViewControllerAnimated:YES];
}
}
}
I can't explain it, but I made a minor change which should have done a better job of trapping an error and instead seems to caused to code to magically start working - which by the way is usually code for you over wrote memory somewhere.
Anyway I did the following and it started working:
Set success = YES before entering the loop
Changed the || test to an && test in both loops
All I changed and yet somehow it just started working...weird...I'm off to test/hammer the thing in case I'm seeing things...

iOS App gets crash in background as changed Settings->Privacy->Contacts My App ON/OFF

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);

ABAddressBookCopyArrayOfAllPeople wrong on device - right on simulator

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);
});

Resources