简单的iOS通讯录操作封装(添加联系人、检查号码是否存在)

SJABHelper.h

#import <Foundation/Foundation.h>

enum {
    ABHelperCanNotConncetToAddressBook, /**< 连接通讯录失败(iOS6之后访问通讯录需要用户许可) */
    ABHelperExistSpecificContact, /**< 号码已存在 */
    ABHelperNotExistSpecificContact /**< 号码不存在 */
};
typedef NSUInteger ABHelperCheckExistResultType;


@interface SJABHelper : NSObject

/**
 *    添加联系人
 *
 *    @param     name     联系人姓名
 *    @param     num     电话号码
 *    @param     label     电话号码的标签备注
 *
 *    @return    是否添加成功
 */
+ (BOOL)addContactName:(NSString*)name phoneNum:(NSString*)num withLabel:(NSString*)label;


/**
 *    查询指定号码是否已存在于通讯录中
 *
 *    @param     phoneNum     电话号码
 *
 *    @return    返回查询结果,详见枚举类型注释
 */
+ (ABHelperCheckExistResultType)existPhone:(NSString*)phoneNum;


@end

 

SJABHelper.m

需要引入 AddressBook framework。

#import "SJABHelper.h"
#import <AddressBook/AddressBook.h>

@implementation SJABHelper

+ (SJABHelper*)shareControl
{
    static SJABHelper *instance;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[SJABHelper alloc] init];
    });
    
    return instance;
}

- (id)init
{
    self = [super init];
    if (self) {

    }
    return self;
}

+ (BOOL)addContactName:(NSString *)name phoneNum:(NSString *)num withLabel:(NSString *)label
{
    return [[SJABHelper shareControl] addContactName:name phoneNum:num withLabel:label];
}

- (BOOL)addContactName:(NSString*)name phoneNum:(NSString*)num withLabel:(NSString*)label
{
    ABRecordRef record = ABPersonCreate();
    CFErrorRef error;

    // 使用 __bridge_retained 关键字将 NSString 转换为 CFString 类型并将内存管理权从 ARC 移交出来
    CFStringRef cf_name = (__bridge_retained CFTypeRef)name;
    CFStringRef cf_num = (__bridge_retained CFTypeRef)num;
    CFStringRef cf_label = (__bridge_retained CFTypeRef)label;
    ABRecordSetValue(record, kABPersonFirstNameProperty, cf_name, &error);
    ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABPersonPhoneProperty);
    ABMultiValueAddValueAndLabel(multi, cf_num, cf_label, NULL);
    ABRecordSetValue(record, kABPersonPhoneProperty, multi, &error);
    CFRelease(multi);
    
    ABAddressBookRef addressBook = nil;
    
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0)
    {
        addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
        
        //等待同意后向下执行
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error)
                                                 {
                                                     dispatch_semaphore_signal(sema);
                                                 });
        
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 
        dispatch_release(sema); 
    } 
    else 
    { 
        addressBook = ABAddressBookCreate(); 
    }
    BOOL success = ABAddressBookAddRecord(addressBook, record, &error);
    if (!success) {
        CFRelease(record);
        CFRelease(addressBook);
        return NO;
    }else{
        success = ABAddressBookSave(addressBook, &error);
        CFRelease(record);
        CFRelease(addressBook);
        return success ? YES : NO;
    }
}

+ (ABHelperCheckExistResultType)existPhone:(NSString *)phoneNum
{
    return [[SJABHelper shareControl] existPhone:phoneNum];
}

- (ABHelperCheckExistResultType)existPhone:(NSString*)phoneNum
{    
    ABAddressBookRef addressBook = nil;
    
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0)
    {
        addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
        
        //等待同意后向下执行
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error)
                                                 {
                                                     dispatch_semaphore_signal(sema);
                                                 });
        
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 
        dispatch_release(sema); 
    } 
    else 
    { 
        addressBook = ABAddressBookCreate(); 
    }
    
    CFArrayRef records;
    if (addressBook) {
        records = ABAddressBookCopyArrayOfAllPeople(addressBook);
        
    }else{
#ifdef DEBUG
        NSLog(@"can not connect to address book");
#endif
        return ABHelperCanNotConncetToAddressBook;
    }
    
    for (int i=0; i<CFArrayGetCount(records); i++) {
        ABRecordRef record = CFArrayGetValueAtIndex(records, i);
        CFTypeRef items = ABRecordCopyValue(record, kABPersonPhoneProperty);
        CFArrayRef phoneNums = ABMultiValueCopyArrayOfAllValues(items);
        if (phoneNums) {
            for (int j=0; j<CFArrayGetCount(phoneNums); j++) {
                CFStringRef cf_phone = CFArrayGetValueAtIndex(phoneNums, j);
                NSString *phone = (__bridge NSString *)cf_phone;
                if ([phoneNum isEqualToString:phone]) {
                    CFRelease(phoneNums);
                    CFRelease(items);
                    CFRelease(records);
                    CFRelease(addressBook);
                    return ABHelperExistSpecificContact;
                }
            }
            CFRelease(phoneNums);
        }
        CFRelease(items);
    }

    CFRelease(records);
    CFRelease(addressBook);
    
    return ABHelperNotExistSpecificContact;
}

@end

 

需要注意的就是iOS6中新的用户隐私保护使得调用 ABAddressBookCreate() 时会弹出alert让用户确认是否允许,需要加上代码:

  // 如果为iOS6以上系统,需要等待用户确认是否允许访问通讯录。
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0)
    {
        addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
        //等待同意后向下执行
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error)
                                                 {
                                                     dispatch_semaphore_signal(sema);
                                                 });
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 
        dispatch_release(sema); 
    } 

不然addressBook在用户确认操作前是NULL,调用会导致程序crash。

posted @ 2012-11-15 11:15  Azure_Sagi  阅读(1266)  评论(1编辑  收藏  举报