ios - 从地址簿中获取所有联系人时崩溃

标签 ios objective-c ios8 addressbook

我正在从地址簿 中获取所有联系人并将它们上传到服务器。但有时它会在 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;            
    }        
}

最佳答案

试试这个方法:

   + (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;
    }

关于ios - 从地址簿中获取所有联系人时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30666654/

相关文章:

iOS DDMathParser 获取字符串中出现的任何 (...)

ios - 在 objective-c 中的字符串数组中进行字符串搜索

ios - iOS 8 中的 MapKit 无法运行

ios - 在 iOS 8 中的纵向锁定应用程序中将单个 View 旋转为横向

objective-c - 使用 Cocoa 渲染像素缓冲区

ios8 - 如何摆脱 Assets 目录编译器警告 "app icon is required for apps ... targeting iOS 7.0 ..."

ios - 工具栏后退按钮不起作用

iphone - UINavigationBar 和 UITableView 之间的工具栏?

ios - NSObject 和 AnyObject 有什么区别?什么时候用这两个?

objective-c - 将随机生成的 NSString 添加到 NSMutableArray 的算法