All of the phone numbers stored at address book have a label like:
"home", "work", "home fax", etc.
I need to change the label of a specific contact putting a custom label named "ATM".
I got this error message:
"Assertion failed: (((ABCMultiValue *)multiValue)->flags.isMutable), function ABMultiValueReplaceLabelAtIndex, file /SourceCache/AddressBook_Sim/AddressBook-796.6/ABMultiValue.c, line 118."
This is my code, there is a comment where I got excepton:
- (void)displayPerson:(ABRecordRef)person {
NSString* name = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
self.firstName.text = name;
NSString* phone = nil;
NSString* lbl = nil;
NSString* newLbl = #"ATM";
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person,
kABPersonPhoneProperty);
if (ABMultiValueGetCount(phoneNumbers) > 0) {
phone = (__bridge_transfer NSString*)
ABMultiValueCopyValueAtIndex(phoneNumbers, 0);
lbl = (__bridge_transfer NSString*)
ABMultiValueCopyLabelAtIndex(phoneNumbers, 0);
//*** HERE IS THE PROBLEM ***
ABMultiValueReplaceLabelAtIndex(phoneNumbers, CFSTR("ATM"), 0);
NSLog(#" - %# (%#)", phone, lbl);
} else {
phone = #"[None]";
lbl = #"[None]";
newLbl = #"[None]";
}
CFRelease(phoneNumbers);
}
How can I change the label of that phone number?
I Found a solution:
The code below is working fine:
- (void)displayPerson:(ABRecordRef)person
{
ABAddressBookRef ab = ABAddressBookCreate();
ABRecordRef record = ABAddressBookGetPersonWithRecordID(ab, ABRecordGetRecordID(person));
CFErrorRef *error = NULL;
ABMultiValueRef phoneNumbers = ABRecordCopyValue(record,kABPersonPhoneProperty);
ABMutableMultiValueRef phoneNumberMV = ABMultiValueCreateMutableCopy(phoneNumbers);
for(CFIndex i=0; i < ABMultiValueGetCount(phoneNumberMV); i++){
NSString *phoneNumber = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phoneNumberMV,i);
//NSSlog(#"phoneNumber = %#", phoneNumber);
if ([#"1128558994" isEqualToString:phoneNumber]) {
//now delete it!!! ;-)
/*
NSSlog(#"phoneNumbers = %#",phoneNumbers);
NSSlog(#"index = %d", i);
*/
//BOOL didRemove = ABMultiValueRemoveValueAndLabelAtIndex(phoneNumberMV,i);
BOOL didChanged = ABMultiValueReplaceLabelAtIndex(phoneNumberMV, (CFStringRef)#"0870", i);
NSLog(#"didRemove = %#\n", (didChanged ? #"TRUE" : #"FALSE"));
BOOL didSet = ABRecordSetValue(record, kABPersonPhoneProperty, phoneNumberMV, nil);
NSLog(#"didSet = %#\n", (didSet ? #"TRUE" : #"FALSE"));
//and save it!
BOOL didSave = ABAddressBookSave(ab, (CFErrorRef *) error);
NSLog(#"didSave = %#\n", (didSave ? #"TRUE" : #"FALSE"));
if (error) {
NSLog(#"ABAddressBookSaveError = %#", error);
}
}
}
CFRelease(ab);
}
Related
I am new in IOS Programming. In my simple app I am storing first name,last name and phone number in NSMutableArray.I have a UITextfield where I get the phone number.I wanna search first name and last name according to mobile number.I am storing firstname, lastname and phone number in different Mutable arrays so how to search firstname and lastname in stored array.
This is my code
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
_firstname = [[NSMutableArray alloc]init];
_lastname = [[NSMutableArray alloc]init];
_number = [[NSMutableArray alloc]init];
_fullname = [[NSMutableArray alloc]init];
_arrContacts = [[NSMutableArray alloc]init];
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));
if (firstName != nil) {
[_firstname addObject:firstName];
}
else{
[_firstname addObject:#"Not Found"];
}
if (lastName != nil) {
[_lastname addObject:lastName];
}
else{
[_lastname addObject:#"Not Found"];
}
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
[[UIDevice currentDevice] name];
NSArray *numbers = (__bridge NSArray *)(ABMultiValueCopyValueAtIndex(phoneNumbers, 0));
if (numbers != nil) {
[_arrContacts addObject:numbers];
NSLog(#"Numbers:%#",_arrContacts);
}
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
_addressBookNum = [_addressBookNum stringByAppendingFormat: #":%#",phoneNumber];
}
}
// NSLog(#"AllNumber:%#",_addressBookNum);
}
else {
// Send an alert telling user to change privacy setting in settings app
}
CFRelease(addressBookRef);
NSLog(#"This is Name: %#",_firstname);
NSLog(#"This is LastName: %#",_lastname);
NSLog(#"Number: %#",_arrContacts);
}
Please suggest some idea to do this
Instead of saving name last name and number in different array store it in single array with dictionary. Suppose NSMutabelArray *details
create dictionary having three values name lastname and number, and add this dictoianry into array,
so it will be easy for you to further use
i m using following code for Backup Full Address Book.
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
CFArrayRef peopleForBackup = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFDataRef vcards = (CFDataRef)ABPersonCreateVCardRepresentationWithPeople(peopleForBackup);
NSString *vcardString = [[NSString alloc] initWithData:(NSData *)CFBridgingRelease(vcards) encoding:NSUTF8StringEncoding];
in Above code i can not get Notes from Contacts.
Please help me, how can i take a full address book as a Backup..?
get Complete Address Book ,
-(void)getAddressbookContacts
{
//Get Contacts From PhoneBook Contacts
NSString *fullName;
UIImage *img;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, nil);
NSInteger numberOfPeople = ABAddressBookGetPersonCount(addressBook);
NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
for (NSInteger i = 0; i < numberOfPeople; i++) {
ABRecordRef person = (__bridge ABRecordRef)allPeople[i];
// get phone numbers
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSString* mobile=#"";
NSString* mobileLabel;
CFIndex numberOfPhoneNumbers = ABMultiValueGetCount(phoneNumbers);
for (CFIndex i = 0; i < numberOfPhoneNumbers; i++)
{
mobileLabel = (__bridge NSString*)ABMultiValueCopyLabelAtIndex(phoneNumbers, i);
// NSLog(#"mobileLabel=%#",mobileLabel);
//Only add numbers who have saved in Mobile or IPhone (eg.Home,Work,..)
if([mobileLabel isEqualToString:(__bridge NSString *)kABPersonPhoneMobileLabel] || [mobileLabel isEqualToString:(__bridge NSString *)kABPersonPhoneIPhoneLabel])
{
NSString *phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phoneNumbers, i));
phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:#"-" withString:#""];
phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:#" " withString:#""];
phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:#"(" withString:#""];
phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:#")" withString:#""];
phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:#" " withString:#""];
// phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:#"+" withString:#""];
// NSLog(#"phoneNumber=%#",phoneNumber);
// contact number should be mobile number or iphone
mobile = (__bridge NSString*)ABMultiValueCopyValueAtIndex(phoneNumbers, i);
NSString *firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
// ABMultiValueRef emailMultiValue = ABRecordCopyValue(person, kABPersonEmailProperty);
//Fetch Email Address of Contact
// NSArray *emailAddresses = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(emailMultiValue);
//NSLog(#"email is %#",emailAddresses);
//Fetch Image of Contact
NSData *imgData = (__bridge NSData *)ABPersonCopyImageData(person);
if(lastName == nil)
{
fullName = firstName;
}
else
{
fullName = [firstName stringByAppendingString:#" "];
fullName = [fullName stringByAppendingString:lastName];
}
if(imgData == nil)
{
//NSLog(#"no image found");
img = [UIImage imageNamed:#"contact"];
}
else
{
img = [UIImage imageWithData:imgData];
}
NSMutableDictionary *dictContactDetails = [[NSMutableDictionary alloc]init];
[dictContactDetails setValue:fullName forKey:#"full_name"];
[dictContactDetails setValue:img forKey:#"profile_image"];
[dictContactDetails setValue:mobile forKey:#"mobile_number"];
[dictContactDetails setValue:phoneNumber forKey:#"number"];
//Add Fullname,Image & number into Array & Display it into Table
[arrayOfInviteContacts addObject:dictContactDetails];
}
}
CFRelease(phoneNumbers);
}
NSLog(#"arrayOfInviteContacts=%lu, %#",(unsigned long)arrayOfInviteContacts.count,arrayOfInviteContacts);
[tblInviteFriends reloadData];
}
I need to make a UITableView which fetches address book contents in it and also a UISearchBar which searches the address book contents.
I need an implementation like this project
http://www.appcoda.com/search-bar-tutorial-ios7/
But the problem is here the data is static and I want to load address book's data in it.
I have created ContactData NSObject Class. In following method, I am creating its object for each contact. At the end, you will get NSMutableArray named contactArr.
-(void)loadContacts{
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
//NSLog(#"%#", addressBook);
});
}
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));
ContactData *dataObj = [[ContactData alloc]init];
NSString *Name = #" ";
if ([firstName length]>0) {
if ([lastName length]>0) {
Name = [NSString stringWithFormat:#"%# %#",firstName,lastName];
}
else{
Name = firstName;
}
}
else{
Name = #" ";
}
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
[[UIDevice currentDevice] name];
//NSLog(#"\n%#\n", [[UIDevice currentDevice] name]);
NSString *phoneNumber = #" ";
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
}
ABMultiValueRef Emails = ABRecordCopyValue(person, kABPersonEmailProperty);
[[UIDevice currentDevice] name];
NSString *Email; //= #" ";
for (CFIndex i = 0; i < ABMultiValueGetCount(Emails); i++) {
Email = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(Emails, i);
}
ABMultiValueRef Addresses = ABRecordCopyValue(person, kABPersonAddressProperty);
NSString *address = #" ";
NSMutableDictionary* addressDict = [[NSMutableDictionary alloc]init];
for (CFIndex i = 0; i < ABMultiValueGetCount(Addresses); i++) {
addressDict = (__bridge_transfer NSMutableDictionary *) ABMultiValueCopyValueAtIndex(Addresses, i);
//NSLog(#"address = %#", addressDict);
NSString * street = [addressDict objectForKey:#"Street"];
NSString * city = [addressDict objectForKey:#"City"];
NSString * state = [addressDict objectForKey:#"State"];
NSString *country = [addressDict objectForKey:#"Country"];
if (country.length>0 || state.length>0 || city.length>0 || street.length>0) {
if (country.length>0 && state.length>0) {
address = [NSString stringWithFormat:#"%#, %#", state,country];
}
else if(country.length>0 && city.length>0){
address = [NSString stringWithFormat:#"%#, %#", city,country];
}
else if (state.length>0 && street.length>0){
address = [NSString stringWithFormat:#"%#, %#", street,country];
}
else if (state.length>0 && city.length>0){
address = [NSString stringWithFormat:#"%#, %#", city,state];
}
else if (state.length>0 && street.length>0){
address = [NSString stringWithFormat:#"%#, %#", street,state];
}
else if (city.length>0 && street.length>0){
address = [NSString stringWithFormat:#"%#, %#", street,city];
}
else if (country.length>0){
address = country;
}
else if (state.length>0){
address = state;
}
else if (city.length>0){
address = city;
}
}
else{
address = #" ";
}
}
//NSLog(#"address = %#", address);
NSData *imgData = (__bridge_transfer NSData *) ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail);
dataObj.name = Name;
dataObj.email = Email;
dataObj.phone = phoneNumber;
dataObj.imageData = imgData;
dataObj.address = address;
[contactArr addObject:dataObj];
}
NSLog(#"contacts loaded");
//NSLog(#"count = %lu", (unsigned long)contactArr.count);
}
else {
//Go to settings and allow access to use contacts[GlobalFunction removeWaitView];
}
}
First make sure you have the correct frameworks imported:
#import <AddressBook/AddressBook.h>
Fetch the contacts of AddressBook like this:
ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );
for ( int i = 0; i < nPeople; i++ )
{
ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, i );
//further code
}
Then populate the UITableView as usual (as per the example you already provided).
Thankfully this framework is being deprecated. The new Contacts API in iOS 9 is gorgeous.
How can i Edit Specific Address book First Name and Last Name Programatically .Could any one Guide me to found this.
Am getting Contact Recode like below.
Email = (
"John-Appleseed#mac.com"
);
First = John;
Last = Appleseed;
numbers = (
"888-555-5512",
"888-555-1212"
);
}
How can i edit the First and last Values.
I used Below code to Fetch contact details from Device
CFErrorRef * error = NULL;
addressBook = ABAddressBookCreateWithOptions(NULL, error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error)
{
if (granted)
{
dispatch_async(dispatch_get_main_queue(), ^{
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));
NSString *name=[NSString stringWithFormat:#"%# %#",firstName,lastName];
NSString *Birthday=(__bridge NSString *)(ABRecordCopyValue(person, kABPersonBirthdayProperty));
NSLog(#"Name:%# %# %#", firstName, lastName,Birthday);
//For Email ids
NSMutableArray *Emails = [NSMutableArray array];
ABMutableMultiValueRef eMail = (__bridge ABMutableMultiValueRef)((__bridge NSString *) ABRecordCopyValue(person, kABPersonEmailProperty));
for (CFIndex i = 0; i < ABMultiValueGetCount(eMail); i++) {
NSString *emails = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(eMail, i);
[Emails addObject:emails];
}
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSMutableArray *numbers = [NSMutableArray array];
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
[numbers addObject:phoneNumber];
}
NSMutableDictionary *contact = [NSMutableDictionary dictionary];
[contact setObject:firstName forKey:#"First"];
[contact setObject:lastName forKey:#"Last"];
[contact setObject:numbers forKey:#"numbers"];
[contact setObject:Emails forKey:#"Email"];
NSLog(#" contacts are %#",contact);
[all_contacts addObject:contact];
NSLog(#"all contacts are %#",all_contacts);
[self.tbl_contacts reloadData];
}
});
}
});
First pick the required contact:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
[self peoplePickerNavigationController:peoplePicker didSelectPerson:person];
return NO;
}
Refer this: for setting and getting first name and last name
ABRecordRef aRecord = ABPersonCreate();
CFErrorRef anError = NULL;
bool didSet;
didSet = ABRecordSetValue(aRecord, kABPersonFirstNameProperty, CFSTR("Katie"), &anError);
if (!didSet) {/* Handle error here. */}
didSet = ABRecordSetValue(aRecord, kABPersonLastNameProperty, CFSTR("Bell"), &anError);
if (!didSet) {/* Handle error here. */}
CFStringRef firstName, lastName;
firstName = ABRecordCopyValue(aRecord, kABPersonFirstNameProperty);
lastName = ABRecordCopyValue(aRecord, kABPersonLastNameProperty);
/* ... Do something with firstName and lastName. ... */
CFRelease(aRecord);
CFRelease(firstName);
CFRelease(lastName);
I have this code for searching in the AddressBook and xcode suggests me that i have potential leaks in firstName, lastName, and another object that is unknown even to xcode. I tried to release the first 2 of them and the warning disappears but my app is crashing. Also i have a random crash on this line, i got it only once but appears in crashlytics for other people. Do you see anything wrong with my code? Thanks.
ABMultiValueRef phoneNumbers = ABRecordCopyValue((__bridge ABRecordRef)evaluatedObject, kABPersonPhoneProperty);
The code. It's purpose is to group all the contacts by the first letter of the name and to duplicate the contacts in case they have multiple numbers.
- (void)filterByKeyword:(NSString*)keyword completionBlock:(AddressBookSearchCompletionBlock)completionBlock {
dispatch_async(abQueue, ^{
[self.filteredContacts removeAllObjects];
// Iterate over original contacts
for (id evaluatedObject in self.allContacts) {
CFStringRef n = ABRecordCopyCompositeName((__bridge ABRecordRef)evaluatedObject);
NSString *name = (__bridge_transfer NSString*)n;
if (name == nil) {
RCLog(#"name is nil. skip this contact");
continue;
}
if (keyword == nil || [[name lowercaseString] rangeOfString:keyword].location != NSNotFound)
{
NSString *key = [[name substringToIndex:1] uppercaseString];
if (key == nil || [key isEqualToString:#"_"]) {
key = #"#";
}
NSMutableArray *arr = [self.filteredContacts objectForKey:key];
if (arr == nil) {
arr = [[NSMutableArray alloc] init];
}
ABMultiValueRef phoneNumbers = ABRecordCopyValue((__bridge ABRecordRef)evaluatedObject, kABPersonPhoneProperty);
signed long num = ABMultiValueGetCount(phoneNumbers);
if (num == 0) {
[arr addObject:evaluatedObject];
}
else {
for (CFIndex i = 0; i < num; i++) {
if (i > 0) {
// Create a separate contact with the alternative phone numbers of a contact
NSString* phoneNumber = (__bridge_transfer NSString*) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
NSString* phoneNumericNumber = [phoneNumber stringByTrimmingCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
if (phoneNumber != nil && phoneNumber.length > 0 && phoneNumericNumber.length > 0) {
ABRecordRef persona = ABPersonCreate();
CFStringRef firstName = ABRecordCopyValue((__bridge ABRecordRef)evaluatedObject, kABPersonFirstNameProperty);
CFStringRef lastName = ABRecordCopyValue((__bridge ABRecordRef)evaluatedObject, kABPersonLastNameProperty);
ABRecordSetValue (persona, kABPersonFirstNameProperty, firstName, nil);
ABRecordSetValue (persona, kABPersonLastNameProperty, lastName, nil);
ABMutableMultiValueRef multiPhone = ABMultiValueCreateMutable(kABMultiStringPropertyType);
bool didAddPhone = ABMultiValueAddValueAndLabel(multiPhone, (__bridge CFTypeRef)(phoneNumber), kABPersonPhoneMobileLabel, NULL);
if (didAddPhone){
ABRecordSetValue(persona, kABPersonPhoneProperty, multiPhone, nil);
}
if (ABPersonHasImageData((__bridge ABRecordRef)evaluatedObject)) {
ABPersonSetImageData(persona, ABPersonCopyImageDataWithFormat((__bridge ABRecordRef)evaluatedObject, kABPersonImageFormatThumbnail), nil);
}
[arr addObject:(__bridge id)persona];
CFRelease(multiPhone);
CFRelease(persona);
}
}
else {
[arr addObject:evaluatedObject];
}
}
}
CFRelease(phoneNumbers);
[self.filteredContacts setObject:arr forKey:key];
RCLog(#"%i contacts for key %#", arr.count, key);
}
}
self.filteredKeys = [[self.filteredContacts allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock();
});
});
}