关于读取手机联系人的小程序制作笔记

关于读取手机联系人的小程序制作笔记

  我们知道,很多APP都希望读取到手机中的联系人信息,今天,就通过学习一个已上架程序Dial4的学习之作记录其中几个重点知识。

首先,我们希望这个软件有一个主页面,上面可以显示出手机中那个的联系人信息,然后,再点击联系人时,可以通过不同的表示从而产生两种不同的效果:直接拨打联系人电话或者推送到另一个页面查看联系人详细信息。

因此,我们首先介绍主界面的相关制作。

一,主页面相关制作

主界面效果图:


我们通过一个tableview来显示每一个联系人,在上部设置一个Call按钮(也可以显示display)来决定点击每一行后是直接拨打电话还是进入详细页面。

接下俩,开始说明主界面制作中重要的几点:

1.    首先,既然要调用手机联系人信息,我们需要先引入一个已有框架AddressBook.framebook,并在头文件中导入包,并且在头文件中定义相应的变量:

#import<UIKit/UIKit.h>
#import<AddressBook/AddressBook.h>//用来进行联系人调用查询
#import "ZjDetailViewController.h"//另一个控制器类,用来显示联系人的详细信息
@interface ZjViewController : UIViewController{
  NSArray*myContacts;//这个数组用来存放所有联系人
  ABAddressBookRefaddressBook;//创建一个联系人类的对象
}
@end


接下俩在.m文件中,我们设置关于左上角的按钮。首先,这个按钮属于一个在UibarItem上新建的UIBarButtonItem。

-(void)doCallorDisplayBtn:(id)sender{
//这个函数用来切换左上方按钮的样式以及对应的功能
    NSString *title= @"Display";
    if(sender!= nil&& [[sender title] compare:@"Display"] == NSOrderedSame){
    //用NSOrderedSame比较是否相等
        title =@"Call";
    }
    //没有点击的时候sender为nil,所以执行上面的部分,点击以后执行了下面的部分,sender不再是nil
    UIBarButtonItem*btn = [[UIBarButtonItem alloc]initWithTitle:titlestyle:UIBarButtonItemStyleBordered target:selfaction:@selector(doCallorDisplayBtn:)];
   self.navigationItem.leftBarButtonItem = btn;
}


也就是当这个按钮显示call则点击以后会进入联系人详细信息页面然后按钮文字变成display。而当按钮显示display,点击则直接拨打联系人电话并且按钮文字变为call。

2.    关于手机联系人权限的检验问题

我们知道,要调用手机中的联系人信息,需要获取联系人权限,因此,需要用下面的函数来

-(BOOL)checkAddressBookAuthorizationStatus:(UITableView*)tableView{
//定义一个授权状态类对象
    ABAuthorizationStatus authStatus=ABAddressBookGetAuthorizationStatus();//创建一个权限状态类的对象
    if(authStatus !=kABAuthorizationStatusAuthorized){
    //表示权限状态并不是已经获取权限,也就是暂时还没有权限
ABAddressBookRequestAccessWithCompletion(addressBook,^(bool granted, CFErrorRef error) {
            if(error){
                NSLog(@"发生错误");
            }else if(!granted){
//出现弹窗,显示相应信息
 UIAlertView *av = [[UIAlertViewalloc]initWithTitle:@"没有授权" message:@"Set permissions inSettings>General>Privacy." delegate:nil cancelButtonTitle:nilotherButtonTitles:@"OK", nil];
 [av show];
}else{
ABAddressBookRevert(addressBook);
//将addressBook中所有联系人(这里包括姓氏,名字,电话号码等多个信息)都添加到数组myContacts中
myContacts =[NSArray arrayWithArray:(__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook)];
                [tableView reloadData];
}
});
}
returnauthStatus == kABAuthorizationStatusAuthorized;//将权限状态设置为已经获取权限
}


通过上面的函数我们就可以检验软件是否获取了联系人读取权限,如果有则继续,如果没有,则出现弹框告诉用户去设置中获取权限。

现在假设我们已经获取了权限,则我们需要开始考虑将联系人信息显示出来了。在这儿要注意一个小细节,对于人名的显示,有两种不同的读取习惯,即名在前姓在后或者姓在前名在后。因此,我们需要通过一个函数来设置联系人信息的显示格式。

-(NSString *)personDisplay:(ABRecordRef)person{
//这个函数用来设置联系人信息如何显示
    NSString *firstName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
    //ABRecordCopyValue函数的作用是从第一个参数(一个联系人记录类的对象)中取出(第二个参数)相关属性值
    NSString *lastName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
    NSString *fullName = nil;
    if(firstName || lastName){
    //判断的对象是一个属性值“联系人姓名显示格式”,它对应两个不同的属性值,分别代表姓在前和名在前
       if(ABPersonGetCompositeNameFormatForRecord(person) ==kABPersonCompositeNameFormatFirstNameFirst){
            fullName = [NSStringstringWithFormat:@"%@ %@",firstName,lastName];
           
        }else{
            fullName = [NSStringstringWithFormat:@"%@ %@",lastName,firstName];
        }
    }else{
    //kABPersonPhoneProperty这个属性值对应的是该联系人信息中包含的电话号码信息,它类似于数组,里面可能包含多个号码
        ABMultiValueRef phoneNumbers =ABRecordCopyValue(person, kABPersonPhoneProperty);
       if(phoneNumbers&&ABMultiValueGetCount(phoneNumbers)>0){
            fullName = (__bridge NSString*)ABMultiValueCopyValueAtIndex(phoneNumbers, 0);
        }
    }
    return fullName;
}


注意,ABRecordRef是一个专门用来存储联系人信息的系统自带类,其中相应的函数ABRecordCopyValue就是用来决定联系人姓名显示的格式。

这里存在一个判断,如果联系人中姓氏和名字都是空,那么直接显示电话号码phoneNumbers这个数组中第一个元素(也就是联系人有好多个电话号码时显示他第一个电话号码)

接下来就是要实现关于tableView的一些代理方法:

首先确定这个联系人列表的组数:

-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView{
    if(myContacts== nil){
    //如果联系人数组中还没有数据
        addressBook = ABAddressBookCreate();
        if([selfcheckAddressBookAuthorizationStatus:tableView]){
        //在检验确定了软件已经获取联系人读取权限后,将联系人信息添加到mycontacts数组中
            myContacts = [NSArrayarrayWithArray:(__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook)];
        }
    }
    return 1;
}


然后确定表格行数,显然就是存放联系人的数组的元素个数:

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    returnmyContacts.count;
}


接下俩设置每一行现实的内容:

-(UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:@"normalCell"];
    //显示联系人姓名
    cell.textLabel.text = [selfpersonDisplay:(__bridge ABRecordRef)([myContactsobjectAtIndex:indexPath.row])];
    //先面试用来设置联系人头像
    NSData *d = (__bridge NSData*)ABPersonCopyImageData((__bridge ABRecordRef)([myContactsobjectAtIndex:indexPath.row]));
    if(nil != d){
        UIImage *image = [UIImageimageWithData:d];
        cell.imageView.image = image;
    }else{
        cell.imageView.image = nil;
    }
//    cell.textLabel.text = @"string";
    return cell;
}


这样的话,我们的首页就可以显示出来我们想要的信息了,但是目前还没有任何实质性的功能。下面我们要考虑点击某一行之后执行的函数:

-(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [[tableViewcellForRowAtIndexPath:indexPath] setSelected:NO animated:YES];
   if([self.navigationItem.leftBarButtonItem.titlecompare:@"Call"] != NSOrderedSame){
        //如果左上角按钮显示call,则执行我们自定义的函数handleRowSelection(直接拨打电话)
        [selfhandleRowSelection:(int)indexPath.row];
    }else{
    //否则进入下一个页面显示联系人详细信息。
        ZjDetailViewController *dvc =[[ZjDetailViewController alloc]initWithStyle:UITableViewStyleGrouped];
        //这里作用是把myContacts中对应的联系人这个参数传给下一个控制器类dvc
        [dvc setPerson:(__bridgeABRecordRef)([myContacts objectAtIndex:indexPath.row])];
        //从数组中选出将要显示的联系人然后传递给“联系人详细信息界面”控制器类的变量person
        [self.navigationControllerpushViewController:dvc animated:YES];
    }
}


这样的话,我们可以先来设置handleRowSelection:函数。

-(void)handleRowSelection:(int)rowIndex{
 
    ABRecordRefperson = (__bridge ABRecordRef)([myContacts objectAtIndex:rowIndex]);
    //先初始化一个联系人类对象,需要从mycontacts数组中通过索引值提取出
    ABMultiValueRef phoneNumbers =ABRecordCopyValue(person, kABPersonPhoneProperty);
    //在这个联系人类中取出联系人的电话号码(注意,有可能不止一个电话号码)
    if(ABMultiValueGetCount(phoneNumbers) ==1){
        //如果联系人只有一个电话号码,直接拨打,通过函数callTheNumber:进行拨号
        [self callTheNumber:(__bridge NSString*)ABMultiValueCopyValueAtIndex(phoneNumbers, 0)];
    }elseif(ABMultiValueGetCount(phoneNumbers)>1){
        //如果有不止一个电话号码,出现弹框,显示出所有的电话号码,然后用户选择摸一个进行拨打
        UIAlertView *av = [[UIAlertViewalloc]initWithTitle:@"请选择拨打号码" message:@"选择拨打号码"delegate:nil cancelButtonTitle:@"取消"otherButtonTitles:nil];
        for(int i =0;i<ABMultiValueGetCount(phoneNumbers);i++){
            [av addButtonWithTitle:(__bridgeNSString *)ABMultiValueCopyValueAtIndex(phoneNumbers, i)];
        }
        [av show];
    }
}


对应于上面的函数,我们还需要两个函数,一个用于拨号,一个用于弹框设置:

-(void)callTheNumber:(NSString *)phoneNum{
    //拨打电话的函数
    NSLog(@"%@",phoneNum);
    NSString *url = [NSStringstringWithFormat:@"tel:%@",phoneNum];
    [[UIApplication sharedApplication]openURL:[NSURL URLWithString:url]];
}
-(void)alertView:(UIAlertView *)alertViewclickedButtonAtIndex:(NSInteger)buttonIndex{
//用于设置弹框的函数
   if(buttonIndex>0){
        [selfcallTheNumber:[alertView buttonTitleAtIndex:buttonIndex]];
    }
}


至此,我们的主页面就基本实现了,而且具有了拨打联系人电话功能,而且支持从多个电话中选择我们希望呼叫的哪一个。下面,我们还需要对两一个控制器类进行代码设置,也就是用来显示联系人详细信息的控制器类。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值