我从地址簿获取所有联系人并将其上传到服务器。但有时候它会在 ABRecordCopyValue(person,kABPersonCompositeNameFormatFirstNameFirst)上崩溃
我无法找到崩溃的情景和原因。它不会每次都崩溃。
+(NSArray *)getAllContacts
{
CFErrorRef *error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
#ifdef DEBUG
NSLog(@"Fetching contact info ----> ");
#endif
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];
for (int i = 0; i < nPeople; i++)
{
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
NSString *fname;
CFTypeRef fnameProperty;
if (person)
{
if (ABRecordCopyValue(person, kABPersonCompositeNameFormatFirstNameFirst))
{
fnameProperty = ABRecordCopyValue(person, kABPersonCompositeNameFormatFirstNameFirst);
fname = (__bridge NSString*)fnameProperty;
}
else
{
fname = @"";
}
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
ABMultiValueRef multiPhones = ABRecordCopyValue(person, kABPersonPhoneProperty);
for(CFIndex i=0;i<ABMultiValueGetCount(multiPhones);i++)
{
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
NSString *phoneNumber = (__bridge NSString *) phoneNumberRef;
[phoneNumbers addObject:phoneNumber];
//NSLog(@"All numbers %@", phoneNumbers);
}
for (int i = 0; i < [phoneNumbers count]; i++)
{
NSMutableDictionary *dicContacts = [[NSMutableDictionary alloc]init];
[dicContacts setValue:fname forKeyPath:@"Name"];
[dicContacts setValue:[[NSUserDefaults standardUserDefaults] valueForKey:@"UserID"] forKeyPath:@"UserID"];
[dicContacts setValue:[phoneNumbers objectAtIndex:i] forKeyPath:@"Contact"];
[dicContacts setValue:@"0" forKeyPath:@"UserContactID"];
[dicContacts setValue:@"AddressBook" forKeyPath:@"ContactType"];
[dicContacts setValue:[[NSUserDefaults standardUserDefaults] valueForKeyPath:@"UserID"] forKeyPath:@"UserID"];
[items addObject:dicContacts];
}
}
}
return items;
} else {
#ifdef DEBUG
NSLog(@"Cannot fetch Contacts :( ");
#endif
return NO;
}
}
答案 0 :(得分:1)
试试这个方法:
+ (NSArray *)getContactsFromPhoneBook {
NSMutableArray *contacts = [NSMutableArray array];
// Request authorization to Address Book
__block BOOL accessGranted = NO;
ABAddressBookRef addressBook;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) {
addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
}
else {
addressBook = ABAddressBookCreate();
}
if (addressBook == NULL) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults boolForKey:SHOW_AB_ACCESS_ERROR]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"Please allow access for working with your contacts in iOS privacy settings"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil, nil];
[alert show];
[defaults setBool:YES forKey:SHOW_AB_ACCESS_ERROR];
}
// Return with empty array
return contacts;
}
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex count = ABAddressBookGetPersonCount(addressBook);
for (int i = 0; i < count; i++) {
NSMutableDictionary *contact = [NSMutableDictionary dictionary];
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
ABMultiValueRef phones = ABRecordCopyValue(ref, kABPersonPhoneProperty);
NSString *firstName = CFBridgingRelease(ABRecordCopyValue(ref, kABPersonFirstNameProperty));
NSString *lastName = CFBridgingRelease(ABRecordCopyValue(ref, kABPersonLastNameProperty));
if ((ABMultiValueGetCount(phones) > 0) && (firstName || lastName)) {
NSArray *phoneNumbersRaw = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(phones));
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] initWithCapacity:phoneNumbersRaw.count];
for (NSString *number in phoneNumbersRaw) {
//phone number must only contain numbers
NSMutableString *strippedNumber = [NSMutableString string];
NSScanner *scanner = [NSScanner scannerWithString:number];
NSCharacterSet *numbers = [NSCharacterSet
characterSetWithCharactersInString:@"0123456789"];
while (![scanner isAtEnd]) {
NSString *buffer;
if ([scanner scanCharactersFromSet:numbers intoString:&buffer]) {
[strippedNumber appendString:buffer];
} else {
[scanner setScanLocation:([scanner scanLocation] + 1)];
}
}
if (strippedNumber.length >0) {
[phoneNumbers addObject:[NSString stringWithString:strippedNumber]];
}
}
NSString *email = @"";
ABMultiValueRef emails = ABRecordCopyValue(ref, kABPersonEmailProperty);
if (ABMultiValueGetCount(emails) > 0) {
email = CFBridgingRelease(ABMultiValueCopyValueAtIndex(emails, 0));
}
[contact setObject:email forKey:@"Email"];
CFRelease(emails);
if (!firstName) {
firstName = @"";
}
[contact setObject:firstName forKey:@"FirstName"];
if (!lastName) {
lastName = @"";
}
[contact setObject:lastName forKey:@"LastName"];
[contact setObject:[NSArray arrayWithArray:phoneNumbers] forKey:@"PhoneNumbers"];
if (phoneNumbers.count != 0) {
[contacts addObject:contact];
}
}
CFRelease(phones);
CFRelease(ref);
}
CFRelease(allPeople);
}
return contacts;
}