I've caught an error:
Fatal Exception: NSRangeException
*** -[__NSArrayI objectAtIndex:]: index 1330 beyond bounds [0 .. 1329]
At string
NSArray *currentABRecords = [ApplicationPhoneDirectory records];
ApplicationPhoneDirectory is NSObject with unique contacts (dict and array).
But I think the error is about working with memory, how can I manage it more properly to avoid appearance of such a problem?
Or, in case if I'm incorrect I can put records part in there.
upd:
static NSArray *RecordsForABInterval(UInt32 start, UInt32 end, CFArrayRef allPeople) {
NSMutableArray *peoples = [NSMutableArray arrayWithCapacity:(end - start) * 2];
for (int i = (int) start; i < end; i++) {
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
NSString *firstName = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSString *fullName = [NSString stringWithFormat:#"%# %#",
firstName.length > 0 ? firstName : #"",
lastName.length > 0 ? lastName : #""];
fullName = [fullName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
ABMutableMultiValueRef phoneList = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex phonesCount = ABMultiValueGetCount(phoneList);
for (int j = 0; j < phonesCount; ++j) {
CFTypeRef ABphone = ABMultiValueCopyValueAtIndex(phoneList, j);
NSString *phone = (NSString *)CFBridgingRelease(ABphone);
NSString *phoneInSMFormat = [phone phoneNumberInSMFormat];
if ([phoneInSMFormat isValidSMPhoneNumber]) {
NSDictionary *record = #{
#"name" : fullName,
#"phone" : phoneInSMFormat,
#"original" : phone
};
[peoples addObject:record];
}
}
if (phoneList != NULL) {
CFRelease(phoneList);
}
}
return peoples;
}
+ (NSArray *)records {
const int MaxAutoreleaseStep = 500;
NSMutableArray *records = [NSMutableArray array];
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
__block BOOL accessGranted = NO;
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
dispatch_async(dispatch_get_main_queue(), ^{
accessGranted = granted;
});
});
} else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
// The user has previously given access, add the contact
accessGranted = YES;
}
else {
// The user has previously denied access
// Send an alert telling user to change privacy setting in settings app
if (addressBook != NULL) {
CFRelease(addressBook);
}
return nil;
}
// TODO: review this logic - should it be a single call to AB?
if (addressBook != NULL) {
CFRelease(addressBook);
}
if (accessGranted) {
ABAddressBookRef addressbook = ABAddressBookCreateWithOptions(NULL, &error);
if (error != NULL) {
if (addressbook != NULL) {
CFRelease(addressbook);
}
return nil;
}
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressbook);
CFIndex peopleCount = ABAddressBookGetPersonCount(addressbook);
for (int start = 0; start < peopleCount; start += MaxAutoreleaseStep) {
#autoreleasepool {
int end = start + MaxAutoreleaseStep;
NSArray *contactListCut = RecordsForABInterval((UInt32) start, (UInt32) MIN((int)peopleCount, end), allPeople);
[records addObjectsFromArray:contactListCut];
}
}
if (allPeople != NULL) {
CFRelease(allPeople);
}
if (addressbook != NULL) {
CFRelease(addressbook);
}
}
return records;
}
upd2:
- (NSString *)phoneNumberInSMFormat {
NSString *phone = [self numericPresentation];
if (phone.length > 0 && [phone characterAtIndex:0] == '8') {
NSMutableString *modifiedString = [phone mutableCopy];
[modifiedString replaceCharactersInRange:NSMakeRange(0, 1) withString:#"7"];
phone = modifiedString;
}
return phone;
}
- (BOOL)isValidSMPhoneNumber {
static NSCharacterSet *characterSet = nil;
if (characterSet == nil) {
characterSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
}
if ([self rangeOfCharacterFromSet:characterSet].location != NSNotFound) {
return NO;
}
if (self.length < 7 || self.length > 12) {
return NO;
}
return [self characterAtIndex:0] != '8';
}
i use linphone SDK in my application. When i start to run app crash happening immediately.
After app start it's call [Fastaddreesbook init] which called [FastAddreesBook reload] which called [FastAddreesBook loadData] which called [FastAddreesBook normalizeSipURI] and exc_bad_access Crash happen in this method:
LinphoneAddress* linphoneAddress = linphone_core_interpret_url([LinphoneManager getLc], [address UTF8String]);
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
/* FastAddressBook.h
*
* Copyright (C) 2011 Belledonne Comunications, Grenoble, France
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __IPHONE_9_0
#import <Contacts/Contacts.h>
#endif
#import "FastAddressBook.h"
#import "LinphoneManager.h"
#import "BundleLocalData.h"
#import "AppUtil.h"
#import "WebserviceUtil.h"
#import "ContactEntry.h"
#import "ContactsViewController.h"
#implementation FastAddressBook
static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef info, void *context);
+ (NSString*)getContactDisplayName:(ABRecordRef)contact {
NSString *retString = nil;
if (contact) {
CFStringRef lDisplayName = ABRecordCopyCompositeName(contact);
if(lDisplayName != NULL) {
retString = [NSString stringWithString:(NSString*)lDisplayName];
CFRelease(lDisplayName);
}
}
return retString;
}
+ (UIImage*)squareImageCrop:(UIImage*)image
{
UIImage *ret = nil;
// This calculates the crop area.
float originalWidth = image.size.width;
float originalHeight = image.size.height;
float edge = fminf(originalWidth, originalHeight);
float posX = (originalWidth - edge) / 2.0f;
float posY = (originalHeight - edge) / 2.0f;
CGRect cropSquare = CGRectMake(posX, posY,
edge, edge);
CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, cropSquare);
ret = [UIImage imageWithCGImage:imageRef
scale:image.scale
orientation:image.imageOrientation];
CGImageRelease(imageRef);
return ret;
}
+ (UIImage*)getContactImage:(ABRecordRef)contact thumbnail:(BOOL)thumbnail {
UIImage* retImage = nil;
if (contact && ABPersonHasImageData(contact)) {
CFDataRef imgData = ABPersonCopyImageDataWithFormat(contact, thumbnail?
kABPersonImageFormatThumbnail: kABPersonImageFormatOriginalSize);
retImage = [UIImage imageWithData:(NSData *)imgData];
if(imgData != NULL) {
CFRelease(imgData);
}
if (retImage != nil && retImage.size.width != retImage.size.height) {
[LinphoneLogger log:LinphoneLoggerLog format:#"Image is not square : cropping it."];
return [self squareImageCrop:retImage];
}
}
return retImage;
}
- (ABRecordRef)getContact:(NSString*)address {
#synchronized (addressBookMap){
return (ABRecordRef)addressBookMap[address];
}
}
+ (BOOL)isSipURI:(NSString*)address {
return [address hasPrefix:#"sip:"] || [address hasPrefix:#"sips:"];
}
+ (NSString*)appendCountryCodeIfPossible:(NSString*)number {
if (![number hasPrefix:#"+"] && ![number hasPrefix:#"00"]) {
NSString* lCountryCode = [[LinphoneManager instance] lpConfigStringForKey:#"countrycode_preference"];
if (lCountryCode && lCountryCode.length>0) {
//append country code
return [lCountryCode stringByAppendingString:number];
}
}
return number;
}
+ (NSString*)normalizeSipURI:(NSString*)address {
NSString *normalizedSipAddress = nil;
LinphoneAddress* linphoneAddress = linphone_core_interpret_url([LinphoneManager getLc], [address UTF8String]);
if(linphoneAddress != NULL) {
char *tmp = linphone_address_as_string_uri_only(linphoneAddress);
if(tmp != NULL) {
normalizedSipAddress = [NSString stringWithUTF8String:tmp];
ms_free(tmp);
}
linphone_address_destroy(linphoneAddress);
}
return normalizedSipAddress;
}
+ (NSString*)normalizePhoneNumber:(NSString*)address {
NSMutableString* lNormalizedAddress = [NSMutableString stringWithString:address];
[lNormalizedAddress replaceOccurrencesOfString:#" "
withString:#""
options:0
range:NSMakeRange(0, lNormalizedAddress.length)];
[lNormalizedAddress replaceOccurrencesOfString:#"("
withString:#""
options:0
range:NSMakeRange(0, lNormalizedAddress.length)];
[lNormalizedAddress replaceOccurrencesOfString:#")"
withString:#""
options:0
range:NSMakeRange(0, lNormalizedAddress.length)];
[lNormalizedAddress replaceOccurrencesOfString:#"-"
withString:#""
options:0
range:NSMakeRange(0, lNormalizedAddress.length)];
return [FastAddressBook appendCountryCodeIfPossible:lNormalizedAddress];
}
+ (BOOL)isAuthorized {
//addme // return !ABAddressBookGetAuthorizationStatus || ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized;
return ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized;
}
- (FastAddressBook*)init {
if ((self = [super init]) != nil) {
addressBookMap = [[NSMutableDictionary alloc] init];
addressBook = nil;
[self reload];
}
self.needToUpdate = FALSE;
if ([CNContactStore class]) {
//ios9 or later
CNEntityType entityType = CNEntityTypeContacts;
if([CNContactStore authorizationStatusForEntityType:entityType] == CNAuthorizationStatusNotDetermined) {
CNContactStore * contactStore = [[CNContactStore alloc] init];
// nslo(#"CNContactStore requesting authorization");
[contactStore requestAccessForEntityType:entityType completionHandler:^(BOOL granted, NSError * _Nullable error) {
// LOGD(#"CNContactStore authorization granted");
}];
} else if([CNContactStore authorizationStatusForEntityType:entityType]== CNAuthorizationStatusAuthorized) {
// LOGD(#"CNContactStore authorization granted");
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateAddressBook:) name:CNContactStoreDidChangeNotification object:nil];
}
return self;
}
-(void) updateAddressBook:(NSNotification*) notif {
// LOGD(#"address book has changed");
self.needToUpdate = TRUE;
}
- (void) checkContactListForJogvoiceList {
// if (![BundleLocalData isLoadingJogvoiceContactList]) {
// [BundleLocalData setLoadingJogvoiceContactList:true];
int maxPhoneNumberSubmit = 200;
NSArray *lContacts = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
NSMutableDictionary *phoneNumberContactsDictionary = [[NSMutableDictionary alloc] init];
NSMutableArray *allPhoneNumberList = [[NSMutableArray alloc] init];
for (id lPerson in lContacts) {
ABRecordRef person = (ABRecordRef)lPerson;
NSArray *phoneList = [AppUtil getContactPhoneList:person];
for (NSString* phoneNumber in phoneList) {
NSMutableArray* contactList = phoneNumberContactsDictionary[phoneNumber];
if (!contactList) {
contactList = [[NSMutableArray alloc] init];
}
[contactList addObject:(__bridge ABRecordRef)person];
phoneNumberContactsDictionary[phoneNumber] = contactList;
}
[allPhoneNumberList addObjectsFromArray:phoneList];
if (allPhoneNumberList.count >= maxPhoneNumberSubmit) {
[self checkContactList:allPhoneNumberList phoneNumberContactsDictionary:phoneNumberContactsDictionary];
}
}
if (allPhoneNumberList.count > 0) {
[self checkContactList:allPhoneNumberList phoneNumberContactsDictionary:phoneNumberContactsDictionary];
}
// ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, self);
// [BundleLocalData setLoadingJogvoiceContactList:false];
// }
}
-(void) checkContactList:(NSMutableArray*)allPhoneNumberList phoneNumberContactsDictionary:(NSMutableDictionary*)phoneNumberContactsDictionary {
[WebserviceUtil apiGetUsersRegistered:[NSArray arrayWithArray:allPhoneNumberList]
success:^(AFHTTPRequestOperation *operation, id responseObject){
NSDictionary* response = responseObject;
for (id phoneNumber in allPhoneNumberList) {
NSNumber *status = response[phoneNumber];
if (status.intValue == 1) { // registered
NSArray* contactList = phoneNumberContactsDictionary[phoneNumber];
for (int index = 0; index < contactList.count; index++) {
ABRecordRef contact = (__bridge ABRecordRef) contactList[index];
[self saveContact:phoneNumber contact:contact];
}
}
}
[self saveAddressBook];
[allPhoneNumberList removeAllObjects];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// nothing
}];
}
-(void) saveContact:(NSString*)phoneNumber contact:(ABRecordRef)contact {
if(contact == NULL || phoneNumber == NULL) {
return;
}
ABMultiValueRef lMap = ABRecordCopyValue(contact, kABPersonInstantMessageProperty);
if (!lMap) {
return;
}
BOOL avafoneAlready = false;
for(int i = 0; i < ABMultiValueGetCount(lMap); ++i) {
ABMultiValueIdentifier identifier = ABMultiValueGetIdentifierAtIndex(lMap, i);
CFDictionaryRef lDict = ABMultiValueCopyValueAtIndex(lMap, i);
if(CFDictionaryContainsKey(lDict, kABPersonInstantMessageServiceKey)) {
if(CFStringCompare((CFStringRef)[LinphoneManager instance].contactSipField, CFDictionaryGetValue(lDict, kABPersonInstantMessageServiceKey), kCFCompareCaseInsensitive) == 0) {
avafoneAlready = true;
}
} else {
//check domain
LinphoneAddress* address = linphone_address_new(((NSString*)CFDictionaryGetValue(lDict,kABPersonInstantMessageUsernameKey)).UTF8String);
if (address) {
if ([[ContactSelection getSipFilter] compare:#"*" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
avafoneAlready = true;
} else {
NSString* domain = [NSString stringWithCString:linphone_address_get_domain(address)
encoding:[NSString defaultCStringEncoding]];
if ([domain compare:[ContactSelection getSipFilter] options:NSCaseInsensitiveSearch] == NSOrderedSame) {
avafoneAlready = true;
}
}
linphone_address_destroy(address);
}
}
CFRelease(lDict);
if(avafoneAlready) {
avafoneAlready = true;
break;
}
}
CFRelease(lMap);
if (avafoneAlready) {
return;
}
NSString *value = [NSString stringWithFormat:#"900%#", phoneNumber];
ContactEntry *entry = nil;
ABMultiValueRef lcMap = ABRecordCopyValue(contact, kABPersonInstantMessageProperty);
if(lcMap != NULL) {
lMap = ABMultiValueCreateMutableCopy(lcMap);
CFRelease(lcMap);
} else {
lMap = ABMultiValueCreateMutable(kABStringPropertyType);
}
ABMultiValueIdentifier index;
NSError* error = NULL;
CFStringRef keys[] = { kABPersonInstantMessageUsernameKey, kABPersonInstantMessageServiceKey};
CFTypeRef values[] = { [value copy], [LinphoneManager instance].contactSipField };
CFDictionaryRef lDict = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 2, NULL, NULL);
if (entry) {
index = ABMultiValueGetIndexForIdentifier(lMap, entry.identifier);
ABMultiValueReplaceValueAtIndex(lMap, lDict, index);
} else {
CFStringRef label = (CFStringRef)[NSString stringWithString:(NSString*)kABPersonPhoneMobileLabel];
ABMultiValueAddValueAndLabel(lMap, lDict, label, &index);
}
if (!ABRecordSetValue(contact, kABPersonInstantMessageProperty, lMap, (CFErrorRef*)&error)) {
[LinphoneLogger log:LinphoneLoggerLog format:#"Can't set contact with value [%#] cause [%#]", value,error.localizedDescription];
CFRelease(lMap);
} else {
if (entry == nil) {
entry = [[[ContactEntry alloc] initWithData:index] autorelease];
}
CFRelease(lDict);
CFRelease(lMap);
/*check if message type is kept or not*/
lcMap = ABRecordCopyValue(contact, kABPersonInstantMessageProperty);
lMap = ABMultiValueCreateMutableCopy(lcMap);
CFRelease(lcMap);
index = ABMultiValueGetIndexForIdentifier(lMap, entry.identifier);
lDict = ABMultiValueCopyValueAtIndex(lMap,index);
// if(!CFDictionaryContainsKey(lDict, kABPersonInstantMessageServiceKey)) {
/*too bad probably a gtalk number, storing uri*/
NSString* username = CFDictionaryGetValue(lDict, kABPersonInstantMessageUsernameKey);
LinphoneAddress* address = linphone_core_interpret_url([LinphoneManager getLc]
,username.UTF8String);
if(address){
char* uri = linphone_address_as_string_uri_only(address);
CFStringRef keys[] = { kABPersonInstantMessageUsernameKey, kABPersonInstantMessageServiceKey};
CFTypeRef values[] = { [NSString stringWithCString:uri encoding:[NSString defaultCStringEncoding]], [LinphoneManager instance].contactSipField };
CFDictionaryRef lDict2 = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 2, NULL, NULL);
ABMultiValueReplaceValueAtIndex(lMap, lDict2, index);
if (!ABRecordSetValue(contact, kABPersonInstantMessageProperty, lMap, (CFErrorRef*)&error)) {
[LinphoneLogger log:LinphoneLoggerLog format:#"Can't set contact with value [%#] cause [%#]", value,error.localizedDescription];
}
CFRelease(lDict2);
linphone_address_destroy(address);
ms_free(uri);
}
// }
CFDictionaryRef lDict = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 2, NULL, NULL);
ABMultiValueReplaceValueAtIndex(lMap, lDict, index);
CFRelease(lMap);
}
CFRelease(lDict);
}
- (void)saveAddressBook {
if( addressBook != nil ){
NSError* err = nil;
if( !ABAddressBookSave(addressBook, (CFErrorRef*)err) ){
Linphone_warn(#"Couldn't save Address Book");
}
}
}
- (void)reload {
NSLog(#"Fastadd reload first is loaded");
CFErrorRef error;
// create if it doesn't exist
if (addressBook == nil) {
addressBook = ABAddressBookCreateWithOptions(NULL, &error);
}
if (addressBook != nil) {
__weak FastAddressBook *weakSelf = self;
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if (!granted) {
Linphone_warn(#"Permission for address book acces was denied: %#", [(__bridge NSError *)error description]);
return;
}
ABAddressBookRegisterExternalChangeCallback(addressBook, sync_address_book, (__bridge void *)(weakSelf));
dispatch_async(dispatch_get_main_queue(), ^(void) {
[weakSelf loadData];
});
});
} else {
Linphone_warn(#"Create AddressBook failed, reason: %#", [(__bridge NSError *)error localizedDescription]);
}
/*
//method1
if(addressBook != nil) {
ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, self);
CFRelease(addressBook);
addressBook = nil;
}
NSError *error = nil;
addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
if(addressBook != NULL) {
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
ABAddressBookRegisterExternalChangeCallback (addressBook, sync_address_book, self);
[self loadData];
});
} else {
[LinphoneLogger log:LinphoneLoggerError format:#"Create AddressBook: Fail(%#)", [error localizedDescription]];
}
*/
}
- (void)loadData {
ABAddressBookRevert(addressBook);
#synchronized (addressBookMap) {
[addressBookMap removeAllObjects];
//melog
NSLog(#"Fastadd loaddata is loaded");
NSArray *lContacts = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
for (id lPerson in lContacts) {
// Phone
{
ABMultiValueRef lMap = ABRecordCopyValue((ABRecordRef)lPerson, kABPersonPhoneProperty);
if(lMap) {
for (int i=0; i<ABMultiValueGetCount(lMap); i++) {
CFStringRef lValue = ABMultiValueCopyValueAtIndex(lMap, i);
CFStringRef lLabel = ABMultiValueCopyLabelAtIndex(lMap, i);
CFStringRef lLocalizedLabel = ABAddressBookCopyLocalizedLabel(lLabel);
NSString* lNormalizedKey = [FastAddressBook normalizePhoneNumber:(NSString*)lValue];
NSString* lNormalizedSipKey = [FastAddressBook normalizeSipURI:lNormalizedKey];
if (lNormalizedSipKey != NULL) lNormalizedKey = lNormalizedSipKey;
addressBookMap[lNormalizedKey] = lPerson;
CFRelease(lValue);
if (lLabel) CFRelease(lLabel);
if (lLocalizedLabel) CFRelease(lLocalizedLabel);
}
CFRelease(lMap);
}
}
// SIP
{
ABMultiValueRef lMap = ABRecordCopyValue((ABRecordRef)lPerson, kABPersonInstantMessageProperty);
if(lMap) {
for(int i = 0; i < ABMultiValueGetCount(lMap); ++i) {
CFDictionaryRef lDict = ABMultiValueCopyValueAtIndex(lMap, i);
BOOL add = false;
if(CFDictionaryContainsKey(lDict, kABPersonInstantMessageServiceKey)) {
CFStringRef contactSipField = (CFStringRef)[LinphoneManager instance].contactSipField;
if (!contactSipField) {
contactSipField = CFStringCreateWithCString(NULL, "SIP", kCFStringEncodingMacRoman);
}
if(CFStringCompare(contactSipField, CFDictionaryGetValue(lDict, kABPersonInstantMessageServiceKey), kCFCompareCaseInsensitive) == 0) {
add = true;
}
} else {
add = true;
}
if(add) {
CFStringRef lValue = CFDictionaryGetValue(lDict, kABPersonInstantMessageUsernameKey);
NSString* lNormalizedKey = [FastAddressBook normalizeSipURI:(NSString*)lValue];
if(lNormalizedKey != NULL) {
addressBookMap[lNormalizedKey] = lPerson;
} else {
addressBookMap[(NSString*)lValue] = lPerson;
}
/*
NSString *lValue =
(__bridge NSString *)CFDictionaryGetValue(lDict, kABPersonInstantMessageUsernameKey);
NSString *lNormalizedKey = [FastAddressBook normalizeSipURI:lValue];
if (lNormalizedKey != NULL) {
[addressBookMap setObject:(__bridge id)(lPerson)forKey:lNormalizedKey];
} else {
[addressBookMap setObject:(__bridge id)(lPerson)forKey:lValue];
}
*/
}
CFRelease(lDict);
}
CFRelease(lMap);
}
}
}
CFRelease(lContacts);
}
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneAddressBookUpdate object:self];
}
void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef info, void *context) {
FastAddressBook* fastAddressBook = (FastAddressBook*)context;
[fastAddressBook loadData];
}
- (void)dealloc {
ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, self);
CFRelease(addressBook);
[addressBookMap release];
[super dealloc];
}
#end
P.S.:
-i use non-arc project
-zombie enable too but nothing change.
-Ivalue is will and thats because crash happening.
Debug Console:
warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available.
LinphoneAddress* linphoneAddress = linphone_core_interpret_url([LinphoneManager getLc], [address UTF8String]);
address is nil. Figure out why that is and you've got your crash source. It likely should be nil as it is probably an optional field in the original record.
That code is a bit of a mess, btw. It isn't following the standard patterns (lots of method prefixed with get, for example). It really should be modernized and have ARC enabled.
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 need to retrieve list of Contacts in iOS.
Here is my code that is not work.
NSMutableArray *myContacts = [[NSMutableArray alloc]init];
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
if (addressBook!=nil)
{
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);
person.firstName = firstName;
[myContacts addObject:person];
}
CFRelease(addressBook);
}
else
{
NSLog(#"Error");
}
How can i get the list of Contacts?
You need to request access to the user's address book first. Set a flag for checking whether the user allowed/denied access.
__block BOOL userDidGrantAddressBookAccess;
CFErrorRef addressBookError = NULL;
if ( ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined ||
ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized )
{
addressBook = ABAddressBookCreateWithOptions(NULL, &addressBookError);
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error){
userDidGrantAddressBookAccess = granted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
else
{
if ( ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusDenied ||
ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusRestricted )
{
// Display an error.
}
}
Then you can call that method you wrote to grab the contacts. Remember to check the value of userDidGrantAddressBookAccess first.
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);
}