//
// AddressBookViewController.m
// UIfont
//
// Created by iOS Developer on 15/8/10.
// Copyright (c) 2015年 iOS Developer. All rights reserved.
//
#import "AddressBookViewController.h"
#import <AddressBook/AddressBook.h> //首先要包含通讯录类头文件
#import <AddressBookUI/AddressBookUI.h>
@interface AddressBookViewController ()<UITableViewDataSource,UITableViewDelegate>
@property(nonatomic,retain)NSMutableArray *dataArr;//Table数据源
@end
@implementation AddressBookViewController
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self addressBookAgree];//先进行授权的判断
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = NO;//iOS7才有的VIewcontroller的新增属性,放到末尾介绍
self.dataArr = [NSMutableArray arrayWithCapacity:0];//为数据源开辟空间,NSMutable的对象只能用Capacity,
//创建一个TableView
UITableView *table = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, 320, self.view.frame.size.height-64-49) style:UITableViewStylePlain];
table.dataSource = self;
table.delegate = self;//实现Table的代理
[self.view addSubview:table];
table.tag = 6666;
}
-(void)addressBookAgree
{
NSLog(@"eadfas");
ABAddressBookRef addressBook = nil;//实例化通讯录对象
if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0)//判断设备版本,因为在iOS好多想的方法规则都进行了升级
{
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);
}
else
{
addressBook = ABAddressBookCreate();//这个方法在ios6以后被弃用了
}
//上面部分是请求通讯录的标准,可直接用,在iOS7就要提示用户 已经禁用了这个权限,
if(ABAddressBookGetAuthorizationStatus() == 1 || ABAddressBookGetAuthorizationStatus() == 2)
{//判断通讯隐私目前状态,1和2表示禁止访问,进行提示
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"有个提醒"
message:@"你已经禁止访问通讯录,请在设置中_隐私_通讯中开启我的权限"
delegate:self
cancelButtonTitle:@"好的!"
otherButtonTitles:nil, nil];
[alert show];
return;
}
[self loadAddress:addressBook];//调用下面打开取通讯录的方法
}
-(void)loadAddress:(ABAddressBookRef)addressBook
{
NSArray* tmpPeoples = (NSArray*)CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));//在通讯录获取所有联系人的全部信息
for(id tmpPerson in tmpPeoples)
{//遍历联系人,tempPerson就是一个联系人
//单项取出属性,关键字ABRecordCopyValue
//获取的联系人单一属性:First name,第一个参数固定就是联系人,第二个参数是要取得值
NSString* tmpFirstName = (NSString*)CFBridgingRelease(ABRecordCopyValue(CFBridgingRetain(tmpPerson), kABPersonFirstNameProperty));
NSString *lastName = (NSString*)CFBridgingRelease(ABRecordCopyValue(CFBridgingRetain(tmpPerson), kABPersonLastNameProperty));
NSLog(@"%@.%@",tmpFirstName,lastName);
//多项取出属性,关键字还是ABRecordCopyValue,但是这次取出来的是一整个项,比如下面取出来的是kABPersonPhoneProperty所对应的联系人电话这个项
ABMultiValueRef phonesArr = ABRecordCopyValue(CFBridgingRetain(tmpPerson), kABPersonPhoneProperty);//获取的联系人多项属性:Generic phone number
NSMutableArray *tempPhoneArr = [NSMutableArray arrayWithCapacity:0];
for(NSInteger j = 0; j < ABMultiValueGetCount(phonesArr); j++)
{ABMultiValueGetCount计算ABMultiValueRef对象的长度,一个联系人的电话项里存了几个电话,就会循环几次
//获得多项中某一项的具体数据,关键字是ABMultiValueCopyValueAtIndex,第一个参数固定就是上面取回来的这个项的数组,第二个参数是下标
NSString* phoneNum = (NSString*)CFBridgingRelease(ABMultiValueCopyValueAtIndex(phonesArr, j));//根据索引获取每一位的电话号码
//获得多项中某一项的具体类型,关键字是ABAddressBookCopyLocalizedLabel,第一个参数还是项的数组,第二个参数是下标
NSString* phoneType = (NSString*)CFBridgingRelease(ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(phonesArr, j)));//根据索引获取每一位的电话类型
[tempPhoneArr addObject:[NSString stringWithFormat:@"%@:%@",phoneType,phoneNum]];//循环多次向这个电话数组中存所有的电话
}
[self.dataArr addObject:@{@"name":[NSString stringWithFormat:@"%@%@",lastName,tmpFirstName],@"phones":tempPhoneArr}];//拼出当前这次大循环这个联系人的名字和电话们
//找到邮箱 kABPersonEmailProperty
ABMultiValueRef emailArr = ABRecordCopyValue(CFBridgingRetain(tmpPerson), kABPersonEmailProperty);
for(NSInteger j = 0; j < ABMultiValueGetCount(emailArr); j++)
{
NSString* phoneNum = (NSString*)CFBridgingRelease(ABMultiValueCopyValueAtIndex(emailArr, j));
NSString* phoneType = (NSString*)CFBridgingRelease(ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(emailArr, j)));
NSLog(@"%@:%@",phoneType,phoneNum);
}
CFRelease(phonesArr);
CFRelease(emailArr);
}
//出了找人的循环后,所有联系人的数据都Ok
UITableView *table = (UITableView*)[self.view viewWithTag:6666];
[table reloadData];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataArr.count;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Address"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"Address"];
}
cell.textLabel.text = self.dataArr[indexPath.row][@"name"];
cell.detailTextLabel.text = ((NSArray*)self.dataArr[indexPath.row][@"phones"]).count >0? self.dataArr[indexPath.row][@"phones"][0]:@"NUll";
return cell;
}
@end
补充:
iOS 7 viewcontroller新增属性automaticallyAdjustsScrollViewInsets,即是否根据按所在界面的navigationbar与tabbar的高度,自动调整scrollview的 inset,此属性默认为YES,这样UIViewController下如果只有一个UIScollView或者其子类,那么会自动留出空白,让scollview滚动经过各种bar下面时能隐约看到内容。但是每个UIViewController只能有唯一一个UIScollView或者其子类,如果超过一个,需要将此属性设置为NO,自己去控制留白以及坐标问题。