Collect string values and add into array - ios

I am writing an app where I want to collect names and phone numbers from a list and add them into an array. How do I do this? I could retrieve first name and last name, but I don't get how to add a phone number in the below code as it is in a different for loop. It might look simple but I am stuck as I am new.
for (i = 0; i < [list count]; i++)
{
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
NSMutableArray *name = [NSMutableArray array];
if(firstName != nil)
[name addObject:firstName];
if(lastName != nil)
[name addObject:lastName];*/
[self displaynames:name];
ABMultiValueRef mobile=ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
for (int k=0;k<ABMultiValueGetCount(mobile); k++)
{
NSString *mobileNo = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(mobile, k);
NSLog(#"mobile number: %#",mobileNo);
}
}
- (void)displaynames:(NSMutableArray*)names
{
for (NSMutableArray* name in names)
{
NSLog(#"MyResult:%# %#",[names objectAtIndex:0],[names objectAtIndex:1]);
}
}
So in the above code I am able to get the first name and last name from the list and add them into the array, similarly how do I get mobile phone number and add into the same array and get the result in the displayNames: function as it is another for loop. Can someone please edit the code and tell me what changes I have to make in the above code. Also in the result everything is being displayed twice why so?

NSMutableArray *contactList=[[NSMutableArray alloc] init];
for (int i=0; i<4; i++) {
NSMutableDictionary *contactInfo=[[NSMutableDictionary alloc] init];
for (int i = 0; i < [list count]; i++)
{
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
if (![firstName isEqualToString:#""]) {
[contactInfo setValue:firstName forKey:#"firstName"];
}
if (![lastName isEqualToString:#""]) {
[contactInfo setValue:lastName forKey:#"lastName"];
}
NSMutableArray *mobileNoArray=[[NSMutableArray alloc] initWithCapacity:ABMultiValueGetCount(mobile)];
ABMultiValueRef mobile=ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
for (int k=0;k<ABMultiValueGetCount(mobile); k++)
{
NSString *mobileNo = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(mobile, k);
[mobileNoArray addObject:mobileNo];
}
if (mobileNoArray.count!=0) {
[contactInfo setObject:mobileNoArray forKey:#"mobileNo"]
}
}
[contactList addObject:contactInfo];
NSLog(#"contact info == %#",contactInfo);
}
NSLog(#"contact list array is %#",contactList);

So, instead using Array you have to use Dictionary to store FirstName, LastName and MobileNo with keyvalue Pair. If you have multiple user than use Array as upper layer, means add your user dictionary into array and when ever you want a user write the code:
for(NSDictionary *userDic in yourArray)
{
NSString *fName = [userDic valueForKey:#"FirstName"];
...
}
This is one of the way...

You can try to add the user info in a dictionary or create a model user object and store in the array. So all the information stays encapsulated in a single object.
self.users = [NSMutableArray array];
for (i = 0; i < [list count]; i++)
{
NSString *firstName = ...
NSString *lastName = ...
NSString *mobileNumber = ...
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
if(firstName)
userInfo[#"FirstName"] = firstName;
if(lastName)
userInfo[#"LastName"] = lastName;
if(mobileNumber)
userInfo[#"MobileNumber"] = mobileNumber;
[self.users addObject:userInfo];
}
You can enumerate using
[self.users enumerateObjectsUsingBlock:^(NSDictionary * userInfo, NSUInteger idx, BOOL *stop) {
NSString *firstName = userInfo[#"FirstName"];
NSString *mobileNumber = userInfo[#"MobileNumber"];
}];
Searching for a single user for a name
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"FirstName == %#",#"aUserName"];
NSDictionary *userInfo = [[self.users filteredArrayUsingPredicate:predicate]lastObject];

Try the following steps:
NSMutableArray *firstNames;
NSMutableArray *LastNames;
NSMutableArray *Mobile_numbers;
NSMutableArray *type_array;
NSMutableArray *firstandlast;
........
-(void)get_arr
{
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *arrayOfPeople = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
NSUInteger index = 0;
firstNames = [[NSMutableArray alloc] init];
Mobile_numbers = [[NSMutableArray alloc] init];
type_array=[[NSMutableArray alloc]init ];
LastNames=[[NSMutableArray alloc]init ];
NSMutableArray *firstandlast;
#try
{
for(index = 0; index<=([arrayOfPeople count]-1); index++)
{
ABRecordRef currentPerson = (__bridge ABRecordRef)[arrayOfPeople objectAtIndex:index];
NSString *type;
ABMultiValueRef phones = (ABMultiValueRef)ABRecordCopyValue(currentPerson, kABPersonPhoneProperty);
for (int i=0; i < ABMultiValueGetCount(phones); i++)
{
//NSString *phone = (NSString *)ABMultiValueCopyValueAtIndex(phones, i);
////NSLog(#"%#", phone);
mobileLabel = (NSString*)ABMultiValueCopyLabelAtIndex(phones, i);
//NSLog(#"MOG:%#",mobileLabel);
if([mobileLabel isEqualToString:#"_$!<Mobile>!$_"]||[mobileLabel isEqualToString:#"_$!<Main>!$_"])
{
//NSLog(#"mobile:");
type=#"mobile";
}
else if ([mobileLabel isEqualToString:#"_$!<Work>!$_"])
{
//NSLog(#"Work:");
type=#"Work";
}
else if ([mobileLabel isEqualToString:#"_$!<Home>!$_"])
{
//NSLog(#"Home:");
type=#"Home";
}
else if ([mobileLabel isEqualToString:#"_$!<Other>!$_"] )
{
//NSLog(#"Other:");
type=#"Other";
}
mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i);
//NSLog(#"GG:%#",mobile);
mobile = [mobile stringByReplacingOccurrencesOfString:#"-"
withString:#""];
mobile = [mobile stringByReplacingOccurrencesOfString:#"("
withString:#""];
mobile = [mobile stringByReplacingOccurrencesOfString:#")"
withString:#""];
mobile = [mobile stringByReplacingOccurrencesOfString:#" "
withString:#""];
[Mobile_numbers addObject:mobile];
[type_array addObject:type];
NSString *currentFirstName = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonFirstNameProperty);
////NSLog(#"NAME:%#",currentFirstName);
if ([currentFirstName length]!=0)
{
//NSLog(#"NAME:%#",currentFirstName);
[firstNames addObject:currentFirstName];
}
else
{
//NSLog(#"NAME:DUMMY");
currentFirstName=#"";
[firstNames addObject:currentFirstName];
}
NSString *currentLast = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonLastNameProperty);
////NSLog(#"NAME:%#",currentFirstName);
if ([currentLast length]!=0)
{
//NSLog(#"NAME:%#",currentLast);
[LastNames addObject:currentLast];
}
else
{
//NSLog(#"NAME:DUMMY");
currentLast=#"";
[LastNames addObject:currentLast];
}
NSString *temp_f_l=[NSString stringWithFormat:#"%# %#",currentFirstName,currentLast];
[firstandlast addObject:temp_f_l];
}
NSLog(#"MOB:%#",Mobile_numbers);
NSLog(#"TYPE:%#",type_array);
NSLog(#"FN:%#",firstNames);
NSLog(#"FN:%#",LastNames);
NSLog(#"FN&LN:%#",firstandlast);
}
}
#catch (NSException *exception)
{
//NSLog(#"CATCH");
}
}
In my Application. I am using this code to store Addressbook contents to Array. I hope it help for you.

Related

In IOS how to fetch the local contact only (stored in iphone not mail synced contacts )using ABaddressbook

am try to fetct the contact
it return the full contact list, from that i need to filter the local contact
NSMutableDictionary *contactDic = [[NSMutableDictionary alloc]init];
contactList = [[NSMutableArray alloc] init];
tableSectionTitles = [[NSMutableArray alloc]init];
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
// CFArrayRef groups = ABAddressBookCopyArrayOfAllGroupsInSource(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSLog(#"nPeople-----%ld",nPeople);
for (int i=0;i < nPeople;i++) {
NSMutableDictionary *dOfPerson=[NSMutableDictionary dictionary];
NSMutableDictionary *keyDic=[NSMutableDictionary dictionary];
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);
NSString *mobileNo = [[NSString alloc] init];
//For username and surname
ABMultiValueRef phones =(__bridge ABMultiValueRef)((__bridge NSString*)ABRecordCopyValue(ref, kABPersonPhoneProperty));
ABMultiValueRef phoneNumbers = ABRecordCopyValue(ref, kABPersonPhoneProperty);
if (phoneNumbers) {
CFIndex numberOfPhoneNumbers = ABMultiValueGetCount(phoneNumbers);
for (CFIndex i = 0; i < numberOfPhoneNumbers; i++) {
CFStringRef label = ABMultiValueCopyLabelAtIndex(phoneNumbers, i);
NSLog(#"Label value------%#",label);
if (label) {
if (CFEqual(label, kABHomeLabel)) {
// it's the user's work phone /
[dOfPerson setObject:(__bridge NSString*)ABMultiValueCopyValueAtIndex(phones, i) forKey:#"Phone"];
} else if (CFEqual(label, kABPersonPhoneMobileLabel)) {
// it's the user's home phone /
[dOfPerson setObject:(__bridge NSString*)ABMultiValueCopyValueAtIndex(phones, i) forKey:#"Phone"];
} else if (CFEqual(label, kABPersonPhoneIPhoneLabel)) {
// other specific cases of your choosing... /
[dOfPerson setObject:(__bridge NSString*)ABMultiValueCopyValueAtIndex(phones, i) forKey:#"Phone"];
}else if (CFEqual(label, kABWorkLabel)) {
// other specific cases of your choosing... /
[dOfPerson setObject:(__bridge NSString*)ABMultiValueCopyValueAtIndex(phones, i) forKey:#"Phone"];
} else {
// it's some other label, such as a custom label /
// [dOfPerson setObject:(__bridge NSString*)ABMultiValueCopyValueAtIndex(phones, i) forKey:#"Phone"];
[dOfPerson setObject:#"" forKey:#"Phone"];
}
CFRelease(label);
}
}
CFRelease(phoneNumbers);
} else {
[dOfPerson setObject:#"" forKey:#"Phone"];
}
// CFStringRef firstName, lastName;
NSString *firstName;
NSString *lastName;
firstName = (__bridge NSString *)(ABRecordCopyValue(ref, kABPersonFirstNameProperty));
lastName = (__bridge NSString *)(ABRecordCopyValue(ref, kABPersonLastNameProperty));
/* if(!firstName) {
firstName = #"N";
} */
if(!firstName && !lastName) {
firstName = #"No Name";
lastName = #"";
}
if(!lastName ) {
lastName = #"";
}
[dOfPerson setObject:[NSString stringWithFormat:#"%# %#", firstName, lastName] forKey:#"name"];
//For Email ids
ABMutableMultiValueRef eMail = ABRecordCopyValue(ref, kABPersonEmailProperty);
if(ABMultiValueGetCount(eMail) > 0) {
[dOfPerson setObject:(__bridge NSString *)ABMultiValueCopyValueAtIndex(eMail, 0) forKey:#"email"];
}
NSString *str = [[NSString stringWithFormat:#"%#", firstName]uppercaseString];
NSLog(#"str title1111------%#",str);
//IMAGE Data
UIImage* image;
if(ABPersonHasImageData(ref)){
NSLog(#"imagedata--------%#",[UIImage imageWithData:(__bridge NSData *)ABPersonCopyImageData(ref)]);
image = [UIImage imageWithData:(__bridge NSData *)ABPersonCopyImageData(ref)];
[dOfPerson setObject:image forKey:#"image"];
}else{
//image = Nil;
[dOfPerson setObject:#"ok3.png" forKey:#"image"];
}
if ([contactList count]<100) { // Final option
NSCharacterSet *s = [NSCharacterSet characterSetWithCharactersInString:#"ABCDEFGHIJKLMNOPQRSTUVWXYZ"];
s = [s invertedSet];
if([str length]>0) {
NSRange r = [[str substringToIndex:1] rangeOfCharacterFromSet:s];
if (r.location != NSNotFound) {
NSLog(#"the string contains illegal characters");
}else{
if(![tableSectionTitles containsObject:[[str substringToIndex:1] uppercaseString]]) {
[tableSectionTitles addObject:[[str substringToIndex:1] uppercaseString]];
[tableSectionTitles sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSLog(#"Section title222------%#",tableSectionTitles);
}
[keyDic setObject:dOfPerson forKey:[[str substringToIndex:1]uppercaseString]];
[contactList addObject:keyDic];
The SDK does not provide an official way for you to query for the contact in the address book that belongs to the user. This has been asked before.

Duplicate contact with ABAddressBook

I'm using ABAddressBook, I can display every contact, but I've some duplicate contact.
I've read this topic : Dealing with duplicate contacts due to linked cards in iOS' Address Book API, but can't fix the problem.
I would like to use this code in mine, but I don't succeed to.. :
NSMutableSet *unifiedRecordsSet = [NSMutableSet set];
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef records = ABAddressBookCopyArrayOfAllPeople(addressBook);
for (CFIndex i = 0; i < CFArrayGetCount(records); i++)
{
NSMutableSet *contactSet = [NSMutableSet set];
ABRecordRef record = CFArrayGetValueAtIndex(records, i);
[contactSet addObject:(__bridge id)record];
NSArray *linkedRecordsArray = (__bridge NSArray *)ABPersonCopyArrayOfAllLinkedPeople(record);
[contactSet addObjectsFromArray:linkedRecordsArray];
// Your own custom "unified record" class (or just an NSSet!)
DAUnifiedRecord *unifiedRecord = [[DAUnifiedRecord alloc] initWithRecords:contactSet];
[unifiedRecordsSet addObject:unifiedRecord];
CFRelease(record);
}
CFRelease(records);
CFRelease(addressBook);
_unifiedRecords = [unifiedRecordsSet allObjects];
Here is my code :
- (void)getPersonOutOfAddressBook
{
//1
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (addressBook != nil) {
NSLog(#"Succesful.");
//2
NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
//3
NSUInteger i = 0; for (i = 0; i < [allContacts count]; i++)
{
Person *person = [[Person alloc] init];
ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i];
//4
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson,
kABPersonFirstNameProperty);
if (firstName == nil)
{
firstName = #"";
}
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
if (lastName == nil)
{
lastName = #"";
}
NSString *fullName = [NSString stringWithFormat:#"%# %#", firstName, lastName];
person.firstName = firstName; person.lastName = lastName;
person.fullName = fullName;
//phone
//5
ABMultiValueRef phones = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
//6
NSUInteger j = 0;
for (j = 0; j < ABMultiValueGetCount(phones); j++) {
NSString *phone = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, j);
if (j == 0) {
person.mainNumber = phone;
}
else if (j==1) person.secondNumber = phone;
}
//7
[person.mainNumber stringByReplacingOccurrencesOfString:#" " withString:#""];
[person.mainNumber stringByReplacingOccurrencesOfString:#"(" withString:#""];
[person.mainNumber stringByReplacingOccurrencesOfString:#")" withString:#""];
[person.mainNumber stringByReplacingOccurrencesOfString:#"+336" withString:#"06"];
[self.tableData addObject:person];
[self.contact addObject:person.fullName];
}
//8
CFRelease(addressBook);
} else {
//9
NSLog(#"Error reading Address Book");
}
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:#"fullName" ascending:YES];
[self.tableData sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
}
If you want to avoid adding duplicates, it's probably easiest to build a set of the ABRecordID values that have already had something added, and only add a contact if it doesn't exist in that set already:
self.tableData = [NSMutableArray array];
NSMutableSet *foundIDs = [NSMutableSet set];
NSArray *allContacts = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
for (id record in allContacts) {
ABRecordRef contactPerson = (__bridge ABRecordRef)record;
ABRecordID recordId = ABRecordGetRecordID(contactPerson);
if (![foundIDs containsObject:#(recordId)]) {
Person *person = [[Person alloc] init];
// get name
person.firstName = CFBridgingRelease(ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty)) ?: #"";
person.lastName = CFBridgingRelease(ABRecordCopyValue(contactPerson, kABPersonLastNameProperty)) ?: #"";
person.fullName = [NSString stringWithFormat:#"%# %#", person.firstName, person.lastName];
// get phones
ABMultiValueRef phones = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
for (NSUInteger j = 0; j < ABMultiValueGetCount(phones); j++) {
// I presume you meant to use mutable string and `replaceOccurrencesOfString`:
NSMutableString *phone = [CFBridgingRelease(ABMultiValueCopyValueAtIndex(phones, j)) mutableCopy];
[phone replaceOccurrencesOfString:#" " withString:#"" options:0 range:NSMakeRange(0, phone.length)];
[phone replaceOccurrencesOfString:#"(" withString:#"" options:0 range:NSMakeRange(0, phone.length)];
[phone replaceOccurrencesOfString:#")" withString:#"" options:0 range:NSMakeRange(0, phone.length)];
[phone replaceOccurrencesOfString:#"+336" withString:#"06" options:0 range:NSMakeRange(0, phone.length)];
if (j == 0) person.mainNumber = phone;
else if (j==1) person.secondNumber = phone;
}
CFRelease(phones);
// add the `Person` record
[self.tableData addObject:person];
// add the ID for this person (and all linked contacts) to our set of `foundIDs`
NSArray *linkedPeople = CFBridgingRelease(ABPersonCopyArrayOfAllLinkedPeople(contactPerson));
if (linkedPeople) {
for (id record in linkedPeople) {
[foundIDs addObject:#(ABRecordGetRecordID((__bridge ABRecordRef)record))];
}
} else {
[foundIDs addObject:#(recordId)];
}
}
}
CFRelease(addressBook);
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"fullName" ascending:YES];
[self.tableData sortUsingDescriptors:#[descriptor]];
Having said that, you probably should iterate through all of the linked contacts and look for phone numbers there, too. Maybe do some validation of the names, too (e.g. if you have one entry for J. D. Salinger and another for John David Salinger, have some algorithm for figuring out which name you want to use). There's a lot you could do. But the above illustrates a minimalistic solution which adds the contact and any linked contacts to the list of contacts already found.

how to save one name string and two different length array of email and phone no

As i guess this is a very simple and basic question.
i am using #import <AddressBook/AddressBook.h> to get the contact info of device and i had successfully implemented the same.
Everythings work fine when i got one phone no and one email from each contact. But when i got multiple phone no's and multiple email then getting crash on my app. I guess i am not using the proper saving method.
So i really want to know how to save one name string and one array of email(different length) and phone no(different length) as group for a contact and same for all other. so that it would not be difficult to reproduce the result later on the detail screen
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));
[values1 addObject:[NSString stringWithFormat:#"%# %#",firstName,lastName]]; //values1 array to save name of contact
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
for (CFIndex j=0; j < ABMultiValueGetCount(emails); j++) {
NSString* email = (__bridge NSString*)ABMultiValueCopyValueAtIndex(emails, j);
NSLog(#"Email:%#", email);
[values2 addObject:[NSString stringWithFormat:#"%#",email]];
} //values2 array to save email associated to that contact
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
NSLog(#"phone:%#", phoneNumber);
[values3 addObject:[NSString stringWithFormat:#"%#",phoneNumber]];
}//values3 array to save different phone no's associated to that contacts
NSDictionary *dict = [[NSDictionary alloc]init];
}
AS now i have three array with details contain details of one contact. Now how can merge these three array values to one so that it would be easy to save and fetch data for multiples or hundreds of contacts
ABAddressBookRef allPeople = ABAddressBookCreate();
CFArrayRef allContacts = ABAddressBookCopyArrayOfAllPeople(allPeople);
CFIndex numberOfContacts = ABAddressBookGetPersonCount(allPeople);
NSLog(#"numberOfContacts------------------------------------%ld",numberOfContacts);
for(int i = 0; i < numberOfContacts; i++){
NSString* name = #"";
NSString* phone = #"";
NSString* email = #"";
ABRecordRef aPerson = CFArrayGetValueAtIndex(allContacts, i);
ABMultiValueRef fnameProperty = ABRecordCopyValue(aPerson, kABPersonFirstNameProperty);
ABMultiValueRef lnameProperty = ABRecordCopyValue(aPerson, kABPersonLastNameProperty);
ABMultiValueRef phoneProperty = ABRecordCopyValue(aPerson, kABPersonPhoneProperty);\
ABMultiValueRef emailProperty = ABRecordCopyValue(aPerson, kABPersonEmailProperty);
NSArray *emailArray = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(emailProperty);
NSArray *phoneArray = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(phoneProperty);
if (fnameProperty != nil) {
name = [NSString stringWithFormat:#"%#", fnameProperty];
}
if (lnameProperty != nil) {
name = [name stringByAppendingString:[NSString stringWithFormat:#" %#", lnameProperty]];
}
if ([phoneArray count] > 0) {
if ([phoneArray count] > 1) {
for (int i = 0; i < [phoneArray count]; i++) {
phone = [phone stringByAppendingString:[NSString stringWithFormat:#"%#\n", [phoneArray objectAtIndex:i]]];
}
}else {
phone = [NSString stringWithFormat:#"%#", [phoneArray objectAtIndex:0]];
}
}
if ([emailArray count] > 0) {
if ([emailArray count] > 1) {
for (int i = 0; i < [emailArray count]; i++) {
email = [email stringByAppendingString:[NSString stringWithFormat:#"%#\n", [emailArray objectAtIndex:i]]];
}
}else {
email = [NSString stringWithFormat:#"%#", [emailArray objectAtIndex:0]];
}
}
NSLog(#"NAME : %#",name);
NSLog(#"PHONE: %#",phone);
NSLog(#"EMAIL: %#",email);
NSLog(#"\n");
}
You can see multiple contact and email in log if contact have.

iOS, create JSON object with ABAddressBookCreate's element

I'm using ABAddressBookCreateWithOptions and ABAddressBookCopyArrayOfAllPeople to achieve all contacts' informations.
I can get person's full name, emails and phone numbers like that:
addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
people = ABAddressBookCopyArrayOfAllPeople(addressBook);
for (CFIndex i = 0; i < CFArrayGetCount(people); i++)
{
ABRecordRef person = CFArrayGetValueAtIndex(people, i);
////get full name////
NSString *fullname = #"";
if (ABRecordCopyValue(person, kABPersonFirstNameProperty)!=NULL){
fullname = [NSString stringWithFormat:#"%# ", ABRecordCopyValue(person, kABPersonFirstNameProperty)];
}
if (ABRecordCopyValue(person, kABPersonMiddleNameProperty)!=NULL){
fullname = [NSString stringWithFormat:#"%#%# ", fullname,ABRecordCopyValue(person, kABPersonMiddleNameProperty)];
}
if (ABRecordCopyValue(person, kABPersonLastNameProperty)!=NULL){
fullname = [NSString stringWithFormat:#"%#%#", fullname,ABRecordCopyValue(person, kABPersonLastNameProperty)];
}
fullname = [fullname stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"fullname: %#",fullname);
////get phone numbers////
ABMultiValueRef phonenumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
if (ABMultiValueGetCount(phonenumbers)>0)
{
for (CFIndex j=0; j < ABMultiValueGetCount(phonenumbers); j++)
{
NSString *phonenumber = (NSString*)CFBridgingRelease(ABMultiValueCopyValueAtIndex(phonenumbers, j));
NSLog(#"phone number: %#",phonenumber);
}
}
CFRelease(phonenumbers);
////get emails////
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
if (ABMultiValueGetCount(emails)>0)
{
for (CFIndex j=0; j < ABMultiValueGetCount(emails); j++)
{
NSString *email = (NSString*)CFBridgingRelease(ABMultiValueCopyValueAtIndex(emails, j));
NSLog(#"email: %#",email);
}
}
CFRelease(emails);
}
CFRelease(addressBook);
CFRelease(people);
Everything works perfectly. But I need to create a JSON object with these informations like that:
[{"name":"Christine Work","phone_numbers":["+99023424234"]},{"name":"Alex Bla","phone_numbers":["+135352125262","+13433452347"],"email_addresses":["bla#bla.com","bla2#bla2.com"]}]
Scenario: If person has email address, than add it to json object, if not, not incude it in json.
If person has more than one phone number or more than one email address add all of them to json.
I'm stuck right here. I know how can I create a json object with NSDictionary :
NSError *error;
NSDictionary* info = [NSDictionary dictionaryWithObjectsAndKeys:
#"alex", #"name",
#"+90225252", #"phones",
nil];
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:info encoding:NSUTF8StringEncoding];
but how can I integrate this code to my scenario in the loop.
Give this a go. Added the necessary code to create the JSON on top of your code. If there are no phone numbers or emails for a contact, NSNull is added for that key. Make sure to check for it when you are pulling the data out of the JSON. Didn't build the code, so let me know if you run into any errors.
NSMutableArray *usersArray = [[NSMutableArray alloc] init];
NSMutableDictionary *singleUserDictionary = [[NSMutableDictionary alloc] init];
NSMutableArray *phoneNumbersArray = [[NSMutableArray alloc] init];
NSMutableArray *emailArray = [[NSMutableArray alloc] init];
for (CFIndex i = 0; i < CFArrayGetCount(people); i++) {
ABRecordRef person = CFArrayGetValueAtIndex(people, i);
////get full name////
NSString *fullname = #"";
if (ABRecordCopyValue(person, kABPersonFirstNameProperty)!=NULL){
fullname = [NSString stringWithFormat:#"%# ", ABRecordCopyValue(person, kABPersonFirstNameProperty)];
}
if (ABRecordCopyValue(person, kABPersonMiddleNameProperty)!=NULL){
fullname = [NSString stringWithFormat:#"%#%# ", fullname,ABRecordCopyValue(person, kABPersonMiddleNameProperty)];
}
if (ABRecordCopyValue(person, kABPersonLastNameProperty)!=NULL){
fullname = [NSString stringWithFormat:#"%#%#", fullname,ABRecordCopyValue(person, kABPersonLastNameProperty)];
}
fullname = [fullname stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"fullname: %#",fullname);
[singleUserDictionary setObject:fullname forKey:#"name"];
////get phone numbers////
ABMultiValueRef phonenumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
if (ABMultiValueGetCount(phonenumbers)>0)
{
for (CFIndex j=0; j < ABMultiValueGetCount(phonenumbers); j++)
{
NSString *phonenumber = (NSString*)CFBridgingRelease(ABMultiValueCopyValueAtIndex(phonenumbers, j));
NSLog(#"phone number: %#",phonenumber);
[phoneNumbersArray addObject:phonenumber];
}
}
else
[phoneNumbersArray addObject:[NSNull null]];
[singleUserDictionary setObject:phoneNumbersArray forKey:#"phone_numbers"];
CFRelease(phonenumbers);
////get emails////
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
if (ABMultiValueGetCount(emails)>0)
{
for (CFIndex j=0; j < ABMultiValueGetCount(emails); j++)
{
NSString *email = (NSString*)CFBridgingRelease(ABMultiValueCopyValueAtIndex(emails, j));
NSLog(#"email: %#",email);
[emailArray addObject:email];
}
}
else
[emailArray addObject:[NSNull null]];
[singleUserDictionary setObject:emailArray forKey:#"email_addresses"];
CFRelease(emails);
[usersArray addObject:[NSDictionary dictionaryWithDictionary:singleUserDictionary]];
[singleUserDictionary removeAllObjects];
[phoneNumbersArray removeAllObjects];
[emailArray removeAllObjects];
}
NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:usersArray options:0 error:&error];
if (error) {
//json success
}
CFRelease(addressBook);
CFRelease(people);
Pseudo-code:
Create outer NSMutableArray.
For each person --
create NSMutableDictionary
insert name
create NSMutableArray and insert into it phone numbers
insert the array into dictionary as "phone_numbers"
repeat for email addresses (if present)
insert dictionary into array
Run outer array through NSJSONSerialization to serialize into an NSData object

ABAddressBookRef leaking in iOS

I'm parsing the address book in iOS but the Leaks instrument is reporting big memory leaks, I can't seem to track the problem down
First I create the address book.
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
This is what I suspect is leaking, but ABAddressBookRef and CFArrayRef get autoreleased right?
The rest of my code is below..
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray *List = [[NSMutableArray alloc] init];
for (int i = 0; i < nPeople; i++) {
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
NSNumber *recordId = [NSNumber numberWithInteger:ABRecordGetRecordID(ref)];
CFStringRef firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
CFStringRef lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
CFDataRef imgData = ABPersonCopyImageData(ref);
ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABMultiStringPropertyType);
multi = ABRecordCopyValue(ref,kABPersonEmailProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) {
CFStringRef email, emailLabel;
emailLabel = ABMultiValueCopyLabelAtIndex(multi, i);
email = ABMultiValueCopyValueAtIndex(multi, i);
NSString *emails = [NSString stringWithFormat: #"%#", (NSString *)email];
if (emails)
{
NSMutableDictionary *addDict = [[NSMutableDictionary alloc] init];
[addDict addObject:emails forKey:#"email"];
[List addObject:addDict];
[addDict release];
}
CFRelease(email);
CFRelease(emailLabel);
}
if (firstName) {
CFRelease(firstName);
}
if (lastName) {
CFRelease(lastName);
}
if (imgData) {
CFRelease(imgData);
}
if (ref) {
CFRelease(ref);
}
CFRelease(multi);
}
//do something with list
[List release];
Ok this works and doesn't leak
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray *List = [[NSMutableArray alloc] init];
for (int x = 0; x < nPeople; x++) {
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, x);
ABMultiValueRef emailMultiValue = ABRecordCopyValue(ref, kABPersonEmailProperty);
NSArray *emailAddresses = [(NSArray *)ABMultiValueCopyArrayOfAllValues(emailMultiValue) autorelease];
for (int i = 0; i < [emailAddresses count]; i++) {
NSString *emails = [emailAddresses objectAtIndex:i];
if (emails)
{
NSMutableDictionary *addDict = [[NSMutableDictionary alloc] init];
[addDict addObject:emails forKey:#"email"];
[List addObject:addDict];
[addDict release];
}
}
if (emailMultiValue)
{
CFRelease(emailMultiValue);
}
if (ref) {
CFRelease(ref);
}
}
//do something with list
[List release];
CFRelease(allPeople);
Actually to eliminate all leaks you also need to be releasing the ABAddressBookRef - just follow Core Foundation naming guidelines - you got the reference using "ABAddressBookCreate()" and any function with Create or Copy needs to be released.
CFErrorRef error = NULL;
ABAddressBookRef addressbk=ABAddressBookCreateWithOptions(NULL, &error);
if (addressbk != nil)
{
NSLog(#"Succesful.");
NSArray *allContacts=(NSArray *)ABAddressBookCopyArrayOfAllPeople(addressbk); //type casting nsarray from CFArrayRef
NSUInteger i = 0;
for (i = 0; i < [allContacts count]; i++)
{
Category *mCategory = [[Category alloc]init];
ABRecordRef contactPerson = ( ABRecordRef)allContacts[i];
NSString *firstName = ( NSString *)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
NSString *lastName = ( NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
NSString *fullName = [NSString stringWithFormat:#"%# %#", firstName, lastName];
mCategory.firstName = firstName;
mCategory.lastName = lastName;
mCategory.fullName = fullName;
//email
ABMultiValueRef emails = ABRecordCopyValue(contactPerson, kABPersonEmailProperty);
NSUInteger j = 0;
for (j = 0; j < ABMultiValueGetCount(emails); j++)
{
NSString *email = ( NSString *)ABMultiValueCopyValueAtIndex(emails, j);
if (j == 0)
{
mCategory.homeEmail = email;
NSLog(#"mCategory.homeEmail = %# ", mCategory.homeEmail);
}
else if (j==1)
mCategory.workEmail = email;
}
[self.arrAddress addObject:mCategory];
[mCategory release];
mCategory=nil;
}
}
CFRelease(addressbk);

Resources