On MAC platform, the ABPerson class has a parentGroups attribute, which tells us which groups the person belongs to. But On IOS platform, there is no such method or property..
How to find out the parent groups of a person? Do I needs to search through all groups one by one?
Thanks.
another thread mentioned ABPersonCopyParentGroups -- but this is wrong -n.a. on ios.
there is no api call so doing this directly is needed
ABRecordRef personToFind = ....
ABRecordID id = ABRecordGetRecordID(personToFind);
NSArray *groups = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllGroups(bookRef);
for(ABGroupRef group in groups) {
NSArray *members = (__bridge_transfer NSArray*)ABGroupCopyAllMembers(group);
for(ABRecordRef member in members) {
if(id == ABRecordGetRecordID(member){
NSLog(#"found in group %#!", ABGroupCopyProperty(group, kABGroupName);
break;
}
}
}
*typed inline, no guarantees -- there are likely typos!
I had difficulties to use Daij-Djan answer, so I rewrote it:
CFArrayRef groupsRef = ABAddressBookCopyArrayOfAllGroups(myAddressBook);
if(groupsRef) {
NSUInteger groupsCount = CFArrayGetCount(groupsRef);
for(NSUInteger idx = 0; idx < groupsCount; ++idx) {
ABRecordRef groupRef = CFArrayGetValueAtIndex(groupsRef, idx);
ABRecordID groupID = ABRecordGetRecordID(groupRef);
CFArrayRef membersRef = ABGroupCopyArrayOfAllMembers(groupRef);
if(membersRef) {
NSUInteger membersCount = CFArrayGetCount(membersRef);
for(NSUInteger idx = 0; idx < membersCount; ++idx) {
ABRecordRef memberRef = CFArrayGetValueAtIndex(membersRef, idx);
ABRecordID memberID = ABRecordGetRecordID(memberRef);
// your code
}
CFRelease(membersRef);
}
}
CFRelease(groupsRef);
}
I scan all groups and people in them, and save person recordID and group recordID to a NSDictionary.
I keep this NDDictionary till app gone, so just need to lookup this NSDictionary for person's group ID.
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
CFArrayRef allGroup = ABAddressBookCopyArrayOfAllGroups( AddressBookManager.addressBook );
CFIndex nGroup = ABAddressBookGetGroupCount(AddressBookManager.addressBook);
NSMutableArray *array = [[NSMutableArray alloc] init];
for (CFIndex index = 0; index < nGroup; index ++)
{
ABRecordRef group = CFArrayGetValueAtIndex(allGroup, index);
ABRecordID groupID = ABRecordGetRecordID(group);
CFArrayRef allPeople = ABGroupCopyArrayOfAllMembers(group);
CFIndex nPeople = CFArrayGetCount(allPeople);
for( CFIndex personIndex = 0; personIndex < nPeople; personIndex++ )
{
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, personIndex );
ABRecordID personID = ABRecordGetRecordID(person);
NSNumber *value = [NSNumber numberWithInt:groupID];
NSString *key = [NSString stringWithFormat:#"%d", personID];
[dic setValue:value forKey:key];
}
CFRelease(allPeople);
}
Related
Guys am working on a calling app for Ios,so naturally i have a dial-pad integrated.
The problem am facing in to get the contact details from number dialed from my dial-pad which i am showing in other screen.
Here is my code
+(PhoneContactModel*) getContactFrom:(NSString *)calledPhoneNumber{
PhoneContactModel *contact=[[PhoneContactModel alloc]init];
ABAddressBookRef addressBook = [AppUtils getCompatibleAdressBook];
CFArrayRef all = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex n = ABAddressBookGetPersonCount(addressBook);
for( int i = 0 ; i < n ; i++ )
{
ABRecordRef ref = CFArrayGetValueAtIndex(all, i);
ABMultiValueRef phones = (ABMultiValueRef)ABRecordCopyValue(ref, kABPersonPhoneProperty);
for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++)
{
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phones, j);
//CFRelease(phones);
NSString *phoneNumber = (__bridge NSString *)phoneNumberRef;
NSLog(#"apputil number %#",[AppUtils getNumberSanatized:phoneNumber]);
if ([phoneNumber isEqualToString:calledPhoneNumber]){
NSLog(#"apputil number matched %#",[AppUtils getNumberSanatized:phoneNumber]);
contact.strFullName = (__bridge_transfer NSString *) ABRecordCopyValue(ref, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *) ABRecordCopyValue(ref, kABPersonLastNameProperty);
contact.strFullName=[contact.strFullName stringByAppendingString:#" "];
if (lastName!=nil){
contact.strFullName=[contact.strFullName stringByAppendingString:lastName];
}
contact.imgContactImge=[AppUtils imageForContact:ref];
contact.strNumber=phoneNumber;
return contact;
}
}
}
contact.strFullName = calledPhoneNumber;
return contact;
}
The problem appears like if i have a Contact A with number 64xxxx... and i dial +164xxxx.. from my dial-pad i don't get the contact details, Also you can see that in the method above i have to run a loop to find the matching contact even if there is a match, so is there a better method out there to do the same
Thanks
I created a better solution
it can be seen here http://codesnight.blogspot.in/2013/11/ios-acces-contacts-from-number.html
I am trying to fetch first name of contact in address book and then to store it in an array.However i am not able to store the contact in array. This is what i tried.
-(void)fetchAddressBook
{
ABAddressBookRef UsersAddressBook = ABAddressBookCreateWithOptions(NULL, NULL);
//contains details for all the contacts
CFArrayRef ContactInfoArray = ABAddressBookCopyArrayOfAllPeople(UsersAddressBook);
//get the total number of count of the users contact
CFIndex numberofPeople = CFArrayGetCount(ContactInfoArray);
//iterate through each record and add the value in the array
for (int i =0; i<numberofPeople; i++) {
ABRecordRef ref = CFArrayGetValueAtIndex(ContactInfoArray, i);
ABMultiValueRef names = (__bridge ABMultiValueRef)((__bridge NSString*)ABRecordCopyValue(ref, kABPersonFirstNameProperty));
NSLog(#"name from address book = %#",names); // works fine.
NSString *contactName = (__bridge NSString *)(names);
[self.reterivedNamesMutableArray addObject:contactName];
NSLog(#"array content = %#", [self.reterivedNamesMutableArray lastObject]);//shows null
}
}
Done .... the array needed to be initialised actually.
I am using the following code to get mobile number (i.e. 1st phone number) of all contacts in my address book. I want to store all those number into NSArray
self.dataSource = [[NSMutableArray alloc]init]; // dataSouce is delared in .h file
ABAddressBookRef addressBook = ABAddressBookCreate();
NSMutableArray *allPeople = (__bridge NSMutableArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
int nPeople = ABAddressBookGetPersonCount(addressBook);
for(int i=0; i < nPeople; i++ ){
ABRecordRef person = (__bridge ABRecordRef)([allPeople objectAtIndex:i]);
NSString *name = #"";
if(ABRecordCopyValue(person, kABPersonFirstNameProperty) != NULL)
name = [[NSString stringWithFormat:#"%#", ABRecordCopyValue(person, kABPersonFirstNameProperty)] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
[_dataSource addObject: name];
ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(person, kABPersonPhoneProperty);
_phoneNumbers = (__bridge NSArray*)ABMultiValueCopyValueAtIndex(phoneNumberProperty, 0);
CFRelease(phoneNumberProperty);
NSLog(#"Phone numbers = %#", _phoneNumbers);
}
but when I use NSLog(#"Phone numbers = %#", _phoneNumbers); the output comes out as
2012-11-07 15:31:06.116 contacts[4938:12b03] Phone numbers = 1 (800) 111-1111
2012-11-07 15:31:06.117 contacts[4938:12b03] Phone numbers = (222) 355-5668
2012-11-07 15:31:06.118 contacts[4938:12b03] Phone numbers = (910) 192-0192
I want the output in NSArray like
Phone numbers = (
"1 (800) 111-1111",
"(222) 355-5668",
"(910) 192-0192"
)
how can I do this ?
you Can Do it Simply like this
self.dataSource = [[NSMutableArray alloc]init]; // dataSouce is delared in .h file
ABAddressBookRef addressBook = ABAddressBookCreate();
NSMutableArray *allPeople = (__bridge NSMutableArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
int nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray *arrContacts = [[NSMutableArray alloc] init];
for(int i=0; i < nPeople; i++ ){
ABRecordRef person = (__bridge ABRecordRef)([allPeople objectAtIndex:i]);
NSString *name = #"";
if(ABRecordCopyValue(person, kABPersonFirstNameProperty) != NULL)
name = [[NSString stringWithFormat:#"%#", ABRecordCopyValue(person, kABPersonFirstNameProperty)] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
[_dataSource addObject: name];
ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(person, kABPersonPhoneProperty);
_phoneNumbers = (__bridge NSArray*)ABMultiValueCopyValueAtIndex(phoneNumberProperty, 0);
CFRelease(phoneNumberProperty);
NSLog(#"Phone numbers = %#", _phoneNumbers);
[arrContacts addObject:_phoneNumbers];
}
NSLog(#"Phone numbers : %#",arrContacts);
I found this via Google and was using this address book code as an example, but found a mistake that I'd correct for others coming here.
When using ABMultiValueCopyValueAtIndex it returns a type CFTypeRef. That function gets just the phone number at that index (in this case at index 0) which in the case of the phone number is a CFStringRef that shouldn't be cast to an NSArray*.
ABMultiValueCopyArrayOfAllValues would be the proper call to get the array of all phone numbers stored in a contact. That can be stored into an array and logged like Sarafaraz is doing in his answer.
NSArray *_phoneNumbers = (__bridge NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumberProperty);
If you just want to get the first phone number you would do this:
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phoneNumberProperty, 0);
NSString *phoneString = (__bridge NSString*)phoneNumberRef;
I'm able to pull the first name and the last name of the contact list from iphone sdk, however I'm unable to fetch the phone number from it. I'm getting the error if I try other way, and the usual way I'm getting other stuff with phone number here is the details with the code:
- (IBAction)buttonmessage {
ABAddressBookRef addressBook = ABAddressBookCreate(); // create address book reference object
NSArray *abContactArray = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); // get address book contact array
NSInteger totalContacts = [abContactArray count];
for(NSUInteger loop= 0 ; loop < totalContacts; loop++)
{
ABRecordRef record = (__bridge ABRecordRef)[abContactArray objectAtIndex:loop]; // get address book record
if(ABRecordGetRecordType(record) == kABPersonType) // this check execute if it is person group
{
ABRecordID recordId = ABRecordGetRecordID(record); // get record id from address book record
recordIdString = [NSString stringWithFormat:#"%d",recordId]; // get record id string from record id
firstNameString = (__bridge NSString*)ABRecordCopyValue(record,kABPersonFirstNameProperty); // fetch contact first name from address book
lastNameString = (__bridge NSString*)ABRecordCopyValue(record,kABPersonLastNameProperty); // fetch contact last name from address book
NSString *phnumber = (__bridge NSString *)ABRecordCopyValue(record, kABPersonPhoneProperty);
myArray2 = [NSArray arrayWithObjects:firstNameString,lastNameString,phnumber,nil];
NSString *m12=[NSString stringWithFormat:#"%#,%#,%#",[myArray2 objectAtIndex:0],[myArray2 objectAtIndex:1],[myArray2 objectAtIndex:2]];
}
Output:
Abdullah,Rashed,ABMultiValueRef 0x80426a0 with 1 value(s)
0: _$!<Mobile>!$_ (0x8042da0) - 0550979691 (0x8042dc0)
2012-05-07 14:43:06.670 Firstphase[2914:207] Hussain,Mahmood,ABMultiValueRef 0x80442d0 with 1 value(s)
0: _$!<Mobile>!$_ (0x8044290) - 055979896 (0x80442b0)
2012-05-07 14:43:06.671 Firstphase[2914:207] Nasir,Jilaani,ABMultiValueRef 0x8046070 with 1 value(s)
0: _$!<Mobile>!$_ (0x8046000) - 055982391 (0x8046020)
2012-05-07 14:43:06.673 Firstphase[2914:207] Ghulam,Basith,ABMultiValueRef 0x8046850 with 1 value(s)
0: _$!<Mobile>!$_ (0x8046810) - 055871943 (0x8046830)
However if you take a close look i'm able to get the firstname and last name without any extra stuff. But I'm not able to get the phone numbers in the same way.
ABMutableMultiValueRef multi;
int multiCount = 0;
multi = ABRecordCopyValue(record, kABPersonPhoneProperty);
multiCount = ABMultiValueGetCount(multi);
for (int i = 0; i < multiCount; i++) {
phoneNumber = (NSString * ) ABMultiValueCopyValueAtIndex(multi, i);
[someArray addObject: phoneNumber];
}
check this:
Your problem may solve with this answer or this.
As of I understand ABRecordCopyValue(ref, kABPersonPhoneProperty) returns some array value. And you are trying to get a String thats why you may face the issue. I didn't tried this solution but think it will work.
Hope this helps.
Try the following:
ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(record, kABPersonPhoneProperty);
NSArray *phoneNumbers = (NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumberProperty);
for (id number in phoneNumbers) {
// do whatever you want
}
The following code will retrieve all the phone numbers from the contact list:-
ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );
for ( int i = 0; i < nPeople; i++ )
{
ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, i );
ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(ref, kABPersonPhoneProperty);
NSArray* phoneNumbers = (NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumberProperty);
CFRelease(phoneNumberProperty);
[phoneNumbers release];
}
It will work..
-(void)displayPerson
{
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (addressBook != nil)
{
NSLog(#"Succesful.");
NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
NSUInteger i = 0;
for (i = 0; i < [allContacts count]; i++)
{
Person *person = [[Person alloc] init];
ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i];
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
NSString *fullName = [NSString stringWithFormat:#"%# %#", firstName, lastName];
NSString *phone=nil;
ABMultiValueRef phoneNumbers = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
if (ABMultiValueGetCount(phoneNumbers) > 0) {
phone = (__bridge_transfer NSString*)
ABMultiValueCopyValueAtIndex(phoneNumbers, 0);
} else {
phone = #"[None]";
}
person.fullname = fullName;
person.phoneNum=phone;
[self.tableData addObject:person];
person=nil;
}
CFRelease(addressBook);
}
}
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;
}