iOS开发------通讯录分组排序(UILocalizedIndexedCollation)

本文介绍了如何在iOS开发中利用`UILocalizedIndexedCollation`进行通讯录分组排序。首先,初始化`UILocalizedIndexedCollation`,接着处理数据源并进行排序,然后实现`UITableViewDataSource`和`UITableViewDelegate`的相关方法,确保在TableView中正确显示分组和内容。通过这些步骤,可以实现类似通讯录的分组效果。
最近写了两篇关于通讯录的博文,通过前两篇博文的简要描述与介绍,基本是能够读出通讯录中的联系人,并能完成对通讯录增删改的操作,但在真实开发中,列出联系人之后是需要分组的,毕竟不能把联系人无规律的排列在 tableView上吧。那么这里就顺水推舟,再介绍一下针对联系人分组特别方便的原生类: UILocalizedIndexedCollation

UILocalizedIndexedCollation

初始化

Demo主页控制器中定义的所有属性

//存放联系人的数组,存放直接请求出的联系人数组
@property (nonatomic, copy)NSArray <YContactObject *> *  contactObjects;

//存放索引的数组,(e.g. A-Z,# in US/English)
@property (nonatomic, copy)NSArray <NSString *> * titles;

//负责进行联系人分组的原生类
@property (nonatomic, strong)UILocalizedIndexedCollation * localizedCollation;

//存放处理过的数组,真正的数据源
@property (nonatomic, copy)NSArray <NSArray *> * handleContactObjects;

//负责请求联系人对象
@property (nonatomic, strong) YContactsManager * contactManager;

在ViewDidLoad中进行属性的初始化

- (void)viewDidLoad {
    [super viewDidLoad];

    //初始化属性
    self.contactManager = [YContactsManager shareInstance];
    self.titles = [NSMutableArray arrayWithCapacity:0];
    self.localizedCollation = [UILocalizedIndexedCollation currentCollation];

    //开始请求
    [self requestContacts];

}

请求的方法:

//开始请求所有的联系人
- (void)requestContacts
{
    __weak typeof(self) copy_self = self;

    //开始请求
    [self.contactManager requestContactsComplete:^(NSArray<YContactObject *> * _Nonnull contacts) {

        //开始赋值
        copy_self.contactObjects = contacts;
        copy_self.titles = copy_self.localizedCollation.sectionTitles;

        //刷新
        [copy_self.tableView reloadData];

    }];
}


处理数据源

_contactObjects这个数组的作用就是存储一些信息,用Swift的话说它就是一个存储属性,真正用到的数据源是_handleContactObjects,所以这里就要重写它的Getter方法,博文的中心就在一下几行代码中:

#pragma mark - localizedCollation Setter
-(NSArray<NSArray *> *)handleContactObjects
{
    //初始化数组返回的数组
    NSMutableArray <NSMutableArray *> * contacts = [NSMutableArray arrayWithCapacity:0];


    /**(注:)
     * 为什么不直接用27,而用count呢,这里取决于初始化方式
     * 初始化方式为[[Class alloc] init],那么这个count = 0
     * 初始化方式为[Class currentCollation],那么这个count = 27
     */

    /**** 根据UILocalizedIndexedCollation的27个Title放入27个存储数据的数组 ****/
    for (NSInteger i = 0; i < self.localizedCollation.sectionTitles.count; i++)
    {
        [contacts addObject:[NSMutableArray arrayWithCapacity:0]];
    }


    //开始遍历联系人对象,进行分组
    for (YContactObject * contactObject in self.contactObjects)
    {
        //获取名字在UILocalizedIndexedCollation标头的索引数
        NSInteger section = [self.localizedCollation sectionForObject:contactObject.nameObject collationStringSelector:@selector(name)];

        //根据索引在相应的数组上添加数据
        [contacts[section] addObject:contactObject];
    }


    //对每个同组的联系人进行排序
    for (NSInteger i = 0; i < self.localizedCollation.sectionTitles.count; i++)
    {
        //获取需要排序的数组
        NSMutableArray * tempMutableArray = contacts[i];

        //如果是直接的属性,直接用该方法排序即可,因为楼主自己构建的Model,name是Model中nameObject的属性,所以此方法不能直接用
        //NSArray * sortArray = [self.localizedCollation sortedArrayFromArray:tempMutableArray collationStringSelector:@selector(name)];


        //这里因为需要通过nameObject的name进行排序,排序器排序(排序方法有好几种,楼主选择的排序器排序)
        NSSortDescriptor * sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"nameObject.name" ascending:true];
        [tempMutableArray sortUsingDescriptors:@[sortDescriptor]];
        contacts[i] = tempMutableArray;

    }

    //返回
    return [NSArray arrayWithArray:contacts];
}

如果对于数组的排序不是很熟,欢迎看一下楼主之前的博文: Objective-C学习-数组排序问题

实现TableViewDataSource方法

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    //返回首字母可能的个数
    return self.titles.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    //根据组数,获取每组联系人的数量
    return self.handleContactObjects[section].count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath];

    //fetch Model
    YContactObject * contactObject = [self.handleContactObjects[indexPath.section] objectAtIndex:indexPath.row];

    //configture cell..
    cell.textLabel.text = contactObject.nameObject.name;
    cell.detailTextLabel.text = contactObject.phoneObject.firstObject.phoneNumber;

    return cell;
}

接下来还需要实现下面的三个数据源方法,为什么要实现呢,固定用法? false : false,除了高中老师会这么教( - - 是不是吐槽了会高中老师),开发文档这么示范的,所以直接复制上的,应该也都知道这几个协议的意义才对.

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return [[[UILocalizedIndexedCollation currentCollation] sectionTitles] objectAtIndex:section];
}

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
    return [[UILocalizedIndexedCollation currentCollation] sectionIndexTitles];
}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
    return [[UILocalizedIndexedCollation currentCollation] sectionForSectionIndexTitleAtIndex:index];
}


实现TableViewDelegate方法

为了避免某组没有数据而出现组标题,实现如下代理方法

#pragma mark - <UITableViewDelegate>
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    //如果没有数据
    if (self.handleContactObjects[section].count == 0)
    {
        return 0;
    }
    return 15;
}

如此通讯录分组就完成了Thanks()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值