I am trying to create a group in my local address book.
I have successfully implemented the code, and it does work well under iOS6 and iOS7 on 32 bit architecture.
However the same code won't do anything on a 64 bit iPad 4. Has anybody experienced something like this?
Here is the code for creating the group:
CFErrorRef error = NULL;
ABRecordRef newGroup = ABGroupCreate();
bool isSucces;
NSLog(#"newGroup: %#", newGroup);
isSucces = ABRecordSetValue(newGroup,
kABGroupNameProperty,
#"KONTAKT",
&error);
if(!isSucces) NSLog(#"error at setting group value");
isSucces = ABAddressBookAddRecord(addressBook, newGroup, &error);
if(!isSucces)NSLog(#"error at adding record to addressbook");
ABAddressBookSave(addressBook, &error);
try this
bool foundIt = NO;
CFArrayRef mygroups = ABAddressBookCopyArrayOfAllGroups(addrBook);
CFIndex numGroups = CFArrayGetCount(mygroups);
for(CFIndex idx=0; idx<numGroups; ++idx) {
ABRecordRef mygroupItem = CFArrayGetValueAtIndex(mygroups, idx);
CFStringRef name = (CFStringRef)ABRecordCopyValue(mygroupItem, kABGroupNameProperty);
bool isMatch = [newName isEqualToString:(NSString *)name];
CFRelease(name);
if(isMatch) {
groupNum = [NSNumber numberWithInt:ABRecordGetRecordID(mygroupItem)];
[self setObject:groupNum forKey:kGroupID];
foundIt = YES;
break;
}
}
CFRelease(mygroups);
if(!foundIt) {
ABRecordRef mygroupItem = ABGroupCreate();
ABRecordSetValue(mygroupItem, kABGroupNameProperty, (CFStringRef *)newName, &error);
if(!error) {
ABAddressBookAddRecord (addrBook, mygroupItem, &error);
ABAddressBookSave(addrBook, &error);
groupNum = [NSNumber numberWithInt:ABRecordGetRecordID(groupItem)];
[self setObject:groupNum forKey:kGroupID];
}
CFRelease(mygroupItem);
}
Related
How to I can edit first name and last on my contact from ABAddressBook.
I used this code to find some contacts with name.
+(CFArrayRef)searchContactOnDevice_fromFullName:(NSString *)FullName{
NSString *searchName = [NSString stringWithFormat:#"%#", FullName];
ABAddressBookRef addressbook = ABAddressBookCreate();
CFStringRef nameRef = (__bridge CFStringRef) searchName;
CFArrayRef allSearchRecords = ABAddressBookCopyPeopleWithName(addressbook, nameRef);
return allSearchRecords;
}
If I want to remove some contacts, I can use this code:
+(void)removeContactWithRecordsList:(CFArrayRef) selectedRecords_
{
ABAddressBookRef addressbook = ABAddressBookCreate();
if (selectedRecords_ != NULL)
{
int count = CFArrayGetCount(selectedRecords_);
for (int i = 0; i < count; ++i)
{
ABRecordRef contact = CFArrayGetValueAtIndex(selectedRecords_, i);
ABAddressBookRemoveRecord(addressbook, contact, nil);
}
}
ABAddressBookSave(addressbook, nil);
CFRelease(addressbook);
}
But, I need to edit firstName and lastName for contacts.
How to I can make it.
This code not tested on Xcode....Its an overall idea which should work a/c to me cause I have done this long time ago...Try this...
//Code to edit contact programmatically...
ABAddressBookRef addressbook = ABAddressBookCreate();
if (selectedRecordsCount_ != NULL)
{
ABRecordRef contact = CFArrayGetValueAtIndex(selectedRecordsCount_, index);
contact.firstName = #"My new first name";
contact.lastName= #"My New last name":
ABAddressBookSave(addressbook, nil);
}
CFRelease(addressbook);
Here the whole idea is to fetch a ABRecordRef object (person object) and modify the same... then save the addressbook ....which will save you contact's edited information.
Please let me know if you have anything more to help with this issue
I'm trying to replace an specific phone number for an specific contact programmatically in iOS, taking the contacts form address book.
I don't know why I can't save the new phone number and refresh the address book to show the change.
I'm doing this:
+(BOOL) changeContactPhoneNumber:(NSString *) phoneSought
forThis:(NSString *) newPhoneNumber{
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef contactSelected;
CFStringRef mobileLabelNumber;
CFErrorRef error = nil;
// Do whatever you want here.
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
for (int i = 0; i < nPeople; i++)
{
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
ABMultiValueRef phones = (ABMultiValueRef)ABRecordCopyValue(ref, kABPersonPhoneProperty);
NSString* mobilePhoneNumber=#"";
if (ABMultiValueGetCount(phones) > 0) {
for (int i=0; i < ABMultiValueGetCount(phones); i++) {
[mobilePhoneNumber release];
mobilePhoneNumber = (NSString*)ABMultiValueCopyValueAtIndex(phones, i);
if([mobilePhoneNumber isEqualToString:phoneSought]){
contactSelected = ref;
mobileLabelNumber = ABMultiValueCopyLabelAtIndex(phones, i);
}
}
}
}
ABMutableMultiValueRef phoneNumberMultiValue = ABMultiValueCreateMutable(kABPersonPhoneProperty);
bool didAddPhone = ABMultiValueAddValueAndLabel(phoneNumberMultiValue ,(__bridge CFTypeRef)newPhoneNumber,mobileLabelNumber, NULL);
if(didAddPhone){
ABRecordSetValue(ABAddressBookGetPersonWithRecordID(addressBook, contactSelected),
kABPersonPhoneProperty,
phoneNumberMultiValue,
nil);
bool bSuccess = ABAddressBookSave(addressBook, &error);
if (!bSuccess) {
NSLog(#"Could not save to address book: %#", error);
} else {
return YES;
}
} else {
NSLog(#"Error editing phone number: %#", error);
error = nil;
}
return NO;
}
You should debug your code and try to figure out whether the format of the phone numbers you are providing to the method are matching or not.
For e.g. when i am logging my contact list phone numbers these are results
Number...555-478-7672
Number...(408) 439-5270
Number...(408) 555-3514
Number...888-555-5512
Number...888-555-1212
Number...555-522-8243
Number...(555) 766-4823
Number...(707) 555-1854
Number...555-610-6679
And i was comparing these number against unformatted number string.
Secondly
ABRecordSetValue(ABAddressBookGetPersonWithRecordID(addressBook, contactSelected),
kABPersonPhoneProperty,
phoneNumberMultiValue,
nil);
Whose actual declaration is
ABRecordSetValue(ABRecordRef record, ABPropertyID property, CFTypeRef value, CFErrorRef* error);
Although ABAddressBookGetPersonWithRecordID returns a ABRecordRef but you already have ABRecordRef contactSelected; so in my view you should use
ABRecordSetValue(contactSelected,kABPersonPhoneProperty,phoneNumberMultiValue,nil);
Please correct me if i am wrong or have misunderstood your code!
I'm trying to develop an app, where users can send messages via iMessage. So I'm able to import the contact list from AddressBook, and to send Messages via MessageUI Framework, but I will like to know which of the contacts imported have also iPhone so they can use iMessage capability. Is there any way to find out from the kABPerson...Property?
Here my code:
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
ABAddressBookRef addressBook = ABAddressBookCreate( );
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
CFErrorRef *error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
for(int i = 0; i < numberOfPeople; i++) {
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
//Something like this ?
BOOL *doeshaveiPhone = (__bridge BOOL *)(ABRecordCopyValue(person, kABPersonPhoneIPhoneLabel));
NSLog(#"Name:%# Surname: %#", firstName, lastName);
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++)
{
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phones, j);
CFStringRef locLabel = ABMultiValueCopyLabelAtIndex(phones, j);
NSString *phoneLabel =(__bridge NSString*) ABAddressBookCopyLocalizedLabel(locLabel);
NSString *phoneNumber = (__bridge NSString *)phoneNumberRef;
CFRelease(phoneNumberRef);
CFRelease(locLabel);
NSLog(#" - %# (%#)", phoneNumber, phoneLabel);
}
}
Your code is the best way to determine if people in the Address Book have iMessage. However, there is a disadvantage: it only works if the user properly sets up their contacts. Too often, fields are improperly set which can make developing applications difficult.
This question has been asked before. Here, the top-voted answer says,
your heurisitic might be ok but it relies on the USER correctly
setting that attribute.
depending on the context it might be good enough / or not .. dont
know.
there is no real way to detect which user really uses ios (no API)
I want to access my address book contacts in my app,i am successfully able to retrieve all contacts from my address book but if sync my i-cloud account in my iPad,then my address book get updated from my i-cloud contacts also,and if now i access my contacts it results in crash.
Kindly help me ,i am completely stuck don't know what to do.
I can easily access the address book contacts but once it get synced from i-cloudand after that i fetch the address book,it results in crash and give me bad excess error.
Here is the code that i used to fetch contacts.
+(NSArray *)getAllContacts
{
CFErrorRef *error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
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);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
#ifdef DEBUG
NSLog(#"Fetching contact info ----> ");
#endif
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];
for (int i = 0; i < nPeople; i++)
{
MContact *contacts = [MContact new];
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
//get First Name and Last Name
contacts.firstName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
contacts.lastName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
if (!contacts.firstName) {
contacts.firstName = #"";
}
if (!contacts.lastName) {
contacts.lastName = #"";
}
NSMutableArray *contactEmails = [NSMutableArray new];
ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty);
for (CFIndex i=0; i<ABMultiValueGetCount(multiEmails); i++) {
CFStringRef contactEmailRef = ABMultiValueCopyValueAtIndex(multiEmails, i);
NSString *contactEmail = (__bridge NSString *)contactEmailRef;
[contactEmails addObject:contactEmail];
// NSLog(#"All emails are:%#", contactEmails);
}
if([contactEmails count]==0){
}
else{
[contacts setemails:contactEmails];
[items addObject:contacts];
}
#ifdef DEBUG
#endif
}
return items;
} else {
#ifdef DEBUG
NSLog(#"Cannot fetch Contacts :( ");
#endif
return NO;
}
}
Did you found exactly where in your code the crash append ? If it is in your "for (int i = 0; i < nPeople; i++)" loop, may be you have an issue on 1 contact only...
PS 1, you should remove line 7 : ....ABAddressBookCreateWithOptions, as you need to check for authorization first....
PS 2, did you really need only contacts from default source ? What about if user have also contact from Lotus Notes or other gmail....
I see one issue but not sure it will solve your crash... You should replace your _bridge by _bridge_transfer :
contacts.firstName = (__bridge_transfer NSString*)ABRecordCopyValue(person,kABPersonFirstNameProperty);
Do the same for lastname....
If it did not solve the crash, I would suggest to try isolate the "person" in your AB witch crash, and try to skip it in your "for loop". This should help us to know if it is only a problem with this person or if it is related to the number of person to load. In my ABLocation App, I know some users have >500 contacts, and they have no PB...
I have a problem when I run this snippet of code on the emulator it works, and I get the id of the group but when I run it on a device the id is set to -1 ... but the error message stays null.
-(NSNumber *)addGroupeToAddressbookWithName:(NSString *)name{
ABAddressBookRef addressBook = ABAddressBookCreate();
CFErrorRef error = NULL;
ABRecordRef group = ABGroupCreate();
ABRecordSetValue(group, kABGroupNameProperty,(__bridge CFStringRef)name, &error);
ABAddressBookAddRecord(addressBook, group, &error);
ABAddressBookSave(addressBook,&error);
NSNumber *gId = [NSNumber numberWithInt:ABRecordGetRecordID(group)];
CFRelease(group);
return gId;
}
I can't figure out what the difference is and how to make it work on a real device.
EDIT: Found that it works if I remove the exchange sync on my phone, but still want it to work while being able to have a exchange account on the phone. So not really solving the problem
EDIT / Answer
Found that it was because exchange don't know about groups, to save a group it is needed to use the right source, also see : Obtaining Specific ABSource from ABAddressBook in iOS 4+
new code:
-(NSNumber *)addGroupeToAddressbookWithName:(NSString *)name{
ABAddressBookRef addressBook = ABAddressBookCreate();
CFErrorRef error = NULL;
CFArrayRef sources = ABAddressBookCopyArrayOfAllSources(addressBook);
CFIndex sourceCount = CFArrayGetCount(sources);
NSNumber *gId = nil;
for (CFIndex i = 0 ; i < sourceCount; i++) {
ABRecordRef currentSource = CFArrayGetValueAtIndex(sources, i);
CFTypeRef sourceType = ABRecordCopyValue(currentSource, kABSourceTypeProperty);
BOOL isMatch = kABSourceTypeLocal == [(__bridge NSNumber *)sourceType intValue];
CFRelease(sourceType);
if (isMatch) {
ABRecordRef group = ABGroupCreateInSource(currentSource);//ABGroupCreate();
ABRecordSetValue(group, kABGroupNameProperty,(__bridge CFStringRef)name, &error);
ABAddressBookAddRecord(addressBook, group, &error);
ABAddressBookSave(addressBook,&error);
gId = [NSNumber numberWithInt:ABRecordGetRecordID(group)];
CFRelease(group);
CFRelease(currentSource);
break;
}
}
CFRelease(sources);
return gId;
}
Found that it was because exchange dont know about groups, to save a group it is needed to use the right source, also see : Obtaining Specific ABSource from ABAddressBook in iOS 4+
new code:
-(NSNumber *)addGroupeToAddressbookWithName:(NSString *)name{
ABAddressBookRef addressBook = ABAddressBookCreate();
CFErrorRef error = NULL;
CFArrayRef sources = ABAddressBookCopyArrayOfAllSources(addressBook);
CFIndex sourceCount = CFArrayGetCount(sources);
NSNumber *gId = nil;
for (CFIndex i = 0 ; i < sourceCount; i++) {
ABRecordRef currentSource = CFArrayGetValueAtIndex(sources, i);
CFTypeRef sourceType = ABRecordCopyValue(currentSource, kABSourceTypeProperty);
BOOL isMatch = kABSourceTypeLocal == [(__bridge NSNumber *)sourceType intValue];
CFRelease(sourceType);
if (isMatch) {
ABRecordRef group = ABGroupCreateInSource(currentSource);//ABGroupCreate();
ABRecordSetValue(group, kABGroupNameProperty,(__bridge CFStringRef)name, &error);
ABAddressBookAddRecord(addressBook, group, &error);
ABAddressBookSave(addressBook,&error);
gId = [NSNumber numberWithInt:ABRecordGetRecordID(group)];
CFRelease(group);
CFRelease(currentSource);
break;
}
}
CFRelease(sources);
return gId;
}