Reputation: 1558
I am trying to retrieve all the contacts from the AddressBook and store the following details in a Mutable array.
The properties are
@property (nonatomic, assign) ABAddressBookRef addressBook;
@property (nonatomic, strong) NSMutableArray *contactList;
@property (nonatomic, strong) IBOutlet UITableView *contactsTableView;
Method to retrieve all contacts
- (void)getAllContacts {
//line moved inside For loop as per Amar's answer.
//NSMutableDictionary *personModel = [[NSMutableDictionary alloc]initWithCapacity:0];
self.addressBook = ABAddressBookCreateWithOptions(NULL, NULL); //iOS 6 and above
CFArrayRef cList = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(self.addressBook, NULL, kABPersonSortByFirstName);
CFIndex nPeople = ABAddressBookGetPersonCount(self.addressBook);
for (int i=0; i<nPeople; i++) {
//Moving this line here per Amar's answer below. The code works perfectly now.
NSMutableDictionary *personModel = [[NSMutableDictionary alloc]initWithCapacity:0];
ABRecordRef personRef = CFArrayGetValueAtIndex(cList, i); // Person will have name, phone number, address, email id and contact image
//Get the name
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(personRef, kABPersonFirstNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(personRef, kABPersonLastNameProperty));
NSString *name = nil;
if(firstName!=nil && lastName!=nil) { //both names are available
name = [NSString stringWithFormat:@"%@ %@",firstName,lastName];
} else if(firstName!=nil && lastName==nil) { //last name not available
name = [NSString stringWithFormat:@"%@",firstName];
} else if(firstName==nil && lastName!=nil) { //first name not available
name = [NSString stringWithFormat:@"%@",lastName];
} else {
name = @"Unnamed Contact"; //both names not available
}
//Get the phone numbers
ABMultiValueRef phoneRef = ABRecordCopyValue(personRef, kABPersonPhoneProperty);
NSMutableArray *phoneNumbers = [NSMutableArray new];
CFIndex ctr = ABMultiValueGetCount(phoneRef);
if(ctr!=0) {
NSString *phoneNumber = nil;
for (CFIndex i=0; i<ctr; i++) {
phoneNumber = (__bridge NSString *) ABMultiValueCopyValueAtIndex(phoneRef, i);
[phoneNumbers addObject:phoneNumber];
}
} else {
[phoneNumbers addObject:@"Phone not available"];
}
//Get the contact address
ABMultiValueRef addrRef = ABRecordCopyValue(personRef, kABPersonAddressProperty);
NSMutableArray *addresses = [NSMutableArray new];
ctr = ABMultiValueGetCount(addrRef);
if(ABMultiValueGetCount(addrRef)!=0) {
for(CFIndex i=0; i<ABMultiValueGetCount(addrRef); i++) {
CFDictionaryRef addr = ABMultiValueCopyValueAtIndex(addrRef, i);
NSString *street = (__bridge NSString *)CFDictionaryGetValue(addr, kABPersonAddressStreetKey);
NSString *city = (__bridge NSString *)CFDictionaryGetValue(addr, kABPersonAddressCityKey);
NSString *state = (__bridge NSString *)CFDictionaryGetValue(addr, kABPersonAddressStateKey);
NSString *zip = (__bridge NSString *)CFDictionaryGetValue(addr, kABPersonAddressZIPKey);
NSString *address = [NSString stringWithFormat:@"%@, %@, %@ %@",street,city,state,zip];
[addresses addObject:address];
}
} else {
[addresses addObject:@"Address not available"];
}
//Get the email address
ABMultiValueRef emailRef = ABRecordCopyValue(personRef, kABPersonEmailProperty);
NSMutableArray *emailAddresses = [NSMutableArray new];
ctr = ABMultiValueGetCount(emailRef);
if(ctr!=0) {
for(CFIndex i=0; i<ctr; i++) {
NSString *eId = (__bridge NSString*)ABMultiValueCopyValueAtIndex(emailRef, i);
[emailAddresses addObject:eId];
}
} else {
[emailAddresses addObject:@"EmailID not available"];
}
//Get the contact image
UIImage *image = nil;
if(ABPersonHasImageData(personRef)) image = (__bridge UIImage *)(ABPersonCopyImageDataWithFormat(personRef, kABPersonImageFormatThumbnail));
//Append the values to a dictionary
[personModel setValue:name forKey:@"cName"];
[personModel setValue:phoneNumbers forKey:@"cPhone"];
[personModel setValue:addresses forKey:@"cAddresses"];
[personModel setValue:emailAddresses forKey:@"cEmailID"];
[personModel setValue:image forKey:@"cImage"];
[self.contactList addObject: personModel];
}
}
In tableView's datasource method cellForRowAtIndexPath
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ContactsCell forIndexPath:indexPath];
cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:16];
cell.textLabel.textColor = [UIColor blackColor];
cell.detailTextLabel.font = [UIFont systemFontOfSize:14.0];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
NSDictionary *model = [self.contactList objectAtIndex:indexPath.row];
NSLog(@"Name:%@",[model valueForKey:@"cName"]);
cell.textLabel.text =[model valueForKey:@"cName"];
return cell;
}
There are four contacts in my address book. However, my tableView always returns the last contact's name (which is "Unnamed Contact" as it has no first/last name).
Unnamed Contact
Unnamed Contact
Unnamed Contact
Unnamed Contact
Any idea why?
Upvotes: 1
Views: 132
Reputation: 3093
every time you store you data in dictionary with same KEY 'cName' " [personModel setValue:name forKey:@"cName"];" Thats why every time value was overwrite with same key and last record was store in dictionary thats why the issue was raised, you need to store your data with different key or get data directly from array rather then dictionary
Upvotes: 0
Reputation: 13222
That's because this line
NSMutableDictionary *personModel = [[NSMutableDictionary alloc]initWithCapacity:0];
is outside the for
-loop. You are creating the dictionary just once before iterating your contact list and modifying the same dictionary. Hence it will always store the last contact info.
Instead, move the above line of code inside the for loop, it will create a new dictionary for storing each contact in your list.
Hope that helps!
Upvotes: 2