iOS 基础学习(10)----通讯录

来源:互联网 发布:金十数据dora是谁 编辑:程序博客网 时间:2024/06/04 18:08

iOS 基础学习(10)—-通讯录

假如在程序中需要获取本机通讯录中的联系人然后通过一个Tableview 展示出来,那么要实现这个功能很简单。
首先,我们要获取系统通讯录,应在程序中加入Apple为开发者提供的的API。
这里写图片描述
在用到通讯录的类里需要导入头文件:

#import <AddressBook/AddressBook.h>#import <AddressBookUI/AddressBookUI.h>

在我的程序中我通过一个数组addressBookTemp来保存通讯录中的联系人。

@property (strong, nonatomic) NSMutableArray *addressBookTemp;

新建一个联系人Model类

@property NSInteger sectionNumber;@property NSInteger recordID;@property (nonatomic, retain) NSString *name;@property (nonatomic, retain) NSString *email;@property (nonatomic, retain) NSString *tel;

那么下面的代码就可以实现将本机通讯录中的联系人保存提取并保存到数组中。

-(void)GetContactsData{        self.addressBookTemp = [[NSMutableArray array]init];        ABAddressBookRef addressBooks = ABAddressBookCreate();        ABAddressBookGetAuthorizationStatus();        if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0)        {            addressBooks =  ABAddressBookCreateWithOptions(NULL, NULL);            //获取通讯录权限            dispatch_semaphore_t sema = dispatch_semaphore_create(0);            ABAddressBookRequestAccessWithCompletion(addressBooks, ^(bool granted, CFErrorRef error){dispatch_semaphore_signal(sema);});            dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);        }        else        {            addressBooks = ABAddressBookCreate();        }        //获取通讯录中的所有人        CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBooks);        //通讯录中人数        CFIndex nPeople = ABAddressBookGetPersonCount(addressBooks);        //循环,获取每个人的个人信息        for (NSInteger i = 0; i < nPeople; i++)        {            //新建一个addressBook model类            TKAddressBook *addressBook = [[TKAddressBook alloc] init];            //获取个人            ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);            //获取个人名字            CFTypeRef abName = ABRecordCopyValue(person, kABPersonFirstNameProperty);            CFTypeRef abLastName = ABRecordCopyValue(person, kABPersonLastNameProperty);            CFStringRef abFullName = ABRecordCopyCompositeName(person);            NSString *nameString = (__bridge NSString *)abName;            NSString *lastNameString = (__bridge NSString *)abLastName;            if ((__bridge id)abFullName != nil) {                nameString = (__bridge NSString *)abFullName;            } else {                if ((__bridge id)abLastName != nil)                {                    nameString = [NSString stringWithFormat:@"%@ %@", nameString, lastNameString];                }            }            addressBook.name = nameString;            addressBook.recordID = (int)ABRecordGetRecordID(person);;            ABPropertyID multiProperties[] = {                kABPersonPhoneProperty,                kABPersonEmailProperty            };            NSInteger multiPropertiesTotal = sizeof(multiProperties) / sizeof(ABPropertyID);            for (NSInteger j = 0; j < multiPropertiesTotal; j++) {                ABPropertyID property = multiProperties[j];                ABMultiValueRef valuesRef = ABRecordCopyValue(person, property);                NSInteger valuesCount = 0;                if (valuesRef != nil) valuesCount = ABMultiValueGetCount(valuesRef);                if (valuesCount == 0) {                    CFRelease(valuesRef);                    continue;                }                //获取电话号码和email                for (NSInteger k = 0; k < valuesCount; k++) {                    CFTypeRef value = ABMultiValueCopyValueAtIndex(valuesRef, k);                    switch (j) {                        case 0: {// Phone number                            addressBook.tel = (__bridge NSString*)value;                            break;                        }                        case 1: {// Email                            addressBook.email = (__bridge NSString*)value;                            break;                        }                    }                    CFRelease(value);                }                CFRelease(valuesRef);            }            //把电话号码保存到数组中            [_addressBookTemp addObject:addressBook];            if (abName) CFRelease(abName);            if (abLastName) CFRelease(abLastName);            if (abFullName) CFRelease(abFullName);        }}

然后可以把addressBookTemp作为Tableview的数据源,显示到tableview上。

@property (weak, nonatomic) IBOutlet UITableView *tableView;
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{    return 45;}-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{return _addressBookTemp.count;}-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    static NSString *cellIdentifier = @"ContactCell%ld";    UITableViewCell *cell = nil;    if (cell == nil){        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];    }    TKAddressBook *book = [_addressBookTemp objectAtIndex:indexPath.row];    cell.textLabel.text = book.name;    cell.textLabel.font = [UIFont systemFontOfSize:14.5f];    UILabel * telLab = [[UILabel alloc]initWithFrame:CGRectMake(self.view.frame.size.width / 3 + 35,0, self.view.frame.size.width / 2, 40)];    telLab.font = [UIFont systemFontOfSize:14.5f];    telLab.textColor = [UIColor darkGrayColor];    telLab.text = book.tel;    [cell addSubview:telLab];    return cell;}

那么问题来了,假如我的通讯录中有2万个联系人,那么用以上的代码就会出现问题,在打开联系人时需要很长时间才可以全部获取到,那么该如何解决这个问题呢。我的方法是把获取联系人的这个方法放到程序将要启动时后台获取。

dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    [self GetContactsData]; });

然后,把获取到的本机的联系人归档。

//沙盒路径#define DOCUMENT   [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]
        NSString *personsArrPath = [NSString stringWithFormat:@"%@/textsFrist.text",DOCUMENT];        //归档        [NSKeyedArchiver archiveRootObject:_addressBookTemp toFile:personsArrPath];

在要显示联系人的Controller上反归档,获取联系人,这样从本地直接加载就提高了很多效率。

    NSString *personsArrPath = [NSString stringWithFormat:@"%@/textsFrist.text",DOCUMENT];    NSArray *newPersonsArr = [NSKeyedUnarchiver unarchiveObjectWithFile:personsArrPath];    self.addressBookTemp = newPersonsArr;    NSLog(@"反归档: %@", newPersonsArr);

但同时问题也来了,假如我的通讯录中有2万个联系人,我没必要直接显示2万个联系人,因为这样我看起来也是很累的。我的解决方案是分页显示。
首先给Tableview添加一个上拉刷新手势,在这里我采用的是第三方框架:MJRefresh,将MJRefresh包导入程序中。引入头文件:

#import "MJRefresh.h"

此处我通过一个变量来记录上拉的次数,

//保存下拉的次数@property (assign, nonatomic) int i;

给Tableview加上一个上拉手势:

    [self.tableView addLegendFooterWithRefreshingTarget:self refreshingAction:@selector(footerRereshing)];- (void)footerRereshing{    ++_i;    NSLog(@"=========%d",_i);    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{        // 刷新表格        [self.tableView reloadData];        // (最好在刷新表格后调用)调用endRefreshing可以结束刷新状态        [self.tableView.footer  endRefreshing];    });}

此处做一个判断,每次加载的行数为:self.view.frame.size.height / 45
如果加载的行数最多只能是联系人列表的总条数。最终得到的代码为:

 if(_addressBookTemp.count < ((self.view.frame.size.height) / 45))    {        return _addressBookTemp.count;    }else    {        if(((self.view.frame.size.height) / 45)  * _i > _addressBookTemp.count)        {            return _addressBookTemp.count;        }else        {            return ((self.view.frame.size.height  45)  * _i;        }    }

ok,最终运行的结果为:
这里写图片描述
这里写图片描述
demo下载地址:
http://download.csdn.net/detail/ningshuang520/9194513
当然以上的代码还是存在问题的,因为我们通讯录中的联系人并不是不变的,当我们的通讯录中的联系人信息改变后,都需要重新更新归档文件。
以上是个人的一些想法,如果有什么不对的地方或者诸位如果有更好的方法欢迎各位提出建议。

0 0