iOS实践:打造一个可以快速索引的城市列表页1. 从plist中获取城市字典2. 对城市的首字母进行排序3. 设置边栏索引4. 关于约束的重要提示5. 完善:封装

相信绝大部分LBS的APP里面,大家都能看到一个带索引的城市列表页面,用来让用户选择所在城市。

我们就一步一步的来实现这个页面,最终效果如下:

Paste_Image.png

最终我们会按照首字母汉语拼音对所有城市进行排序,可以通过右侧的首字母索引来快速定位到城市。

1. 从plist中获取城市字典

1.1 准备素材,下载文件

城市列表(带拼音首字母的),下载地址:

链接: https://pan.baidu.com/s/1nvPNYJJ 密码: cjpw

1.2 从plist中读取出所有的城市。

- (NSDictionary *)loadCityListData{
    
    return [NSDictionary dictionaryWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"cityList.plist" withExtension:nil]];
}

1.3 取出字典中所有的key

  • 字典中有一个属性allKeys,可以取出字典中所有的key。这是一个只读的属性。
  • 根据allKeys就能知道字典中有多少组,去对应的数据源设置返回数据。
@property (readonly, copy) NSArray<KeyType> *allKeys;

2. 对城市的首字母进行排序

  • 对所有字典key的数组中的内容进行排序
  • 对于排序,系统提供了两种办法可以进行排序。我们就不用再写什么冒泡儿、选择之类的算法了,直接来就可以用。

2.1 方法一:使用方法进行排序:升序

    _firstLetterOfCitys = [_firstLetterOfCitys sortedArrayUsingSelector:@selector(compare:)];

2.2 使用block进行排序:可以选择排序的方法

    _firstLetterOfCitys = [_firstLetterOfCitys sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
//        升序排序
        return [obj1 compare:obj2];
        
//        将序排序
        return [obj2 compare:obj1];
        
//        乱序
        return arc4random_uniform(10) % 3 - 1;
        
    }];
  • 之所以是能够排序,是每次obj1和obj2比较都进行了一次排序。排序结果记录在了NSComparisonReuslt中。
  • NSComparisonReuslt是一个枚举。通过操作两数比较的结果,进行排序。如果两数比较的结果一会儿是-1,一会儿是0,一会儿是1,那排序出来的结果也就是乱的。

官方对此说明:

typedef NS_ENUM(NSInteger, NSComparisonResult) {NSOrderedAscending = -1L, NSOrderedSame, NSOrderedDescending};

3. 设置边栏索引

  • 边栏的索引显示的文字和实际跳转没有直接关系。
  • 边栏索引无论写什么,都是按照实际的key值进行跳转的。
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView{
    return _firstLetterOfCitys;
}

4. 关于约束的重要提示

  • 所有的类方法在执行初始化的时候都需要先去看看类里面初始化的方法首选项。

以UITableView为例

NS_CLASS_AVAILABLE_IOS(2_0) @interface UITableView : UIScrollView <NSCoding>

- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER; // must specify style at creation. -initWithFrame: calls this with UITableViewStylePlain
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;

官方说明的意思是说,当执行init的时候,系统要求执行了两个初始化方法。

问题来了:如果在初始化的时候,写成了[[UITableView alloc] init],在编译的时候实际上还是执行了两个初始化方法。第一个初始化方法中要求传入frame,此时因为没有传入参数,frame就会被默认为{0.0.0.0}。

为了解决这个问题,当view有了frame之后,就需要重新给tableView设置frame。是用以下方法进行设置:

- (void)layoutSubviews{
    [super layoutSubviews];
    _tableView.frame = self.bounds;
}

5. 完善:封装

因为城市列表今后我们很有可能会在其他项目里面使用,但我们又不确定以后再使用的时候是用StoryBoard调用还是代码调用。所以我们还要进一步处理一下。

//当从XIB或者UIStoryboard中创建UITableView的时候加载此方法
- (void)awakeFromNib{
    [super awakeFromNib];
    [self createCityListTableView];
}

//使用代码创建的时候加载此方法
- (instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        [self createCityListTableView];
    }
    
    return self;
}

这样就算是封装好了,以后不管是SB还是代码方式,都可以直接的把刚才写好的城市列表进行引用了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏web编程技术分享

《从案例中学习JavaScript》之实现对话效果

34712
来自专栏大内老A

扩展UltraGrid控件实现对所有数据行的全选功能[Source Code下载]

在前面一篇文章中,我通过对三种Infragistics 控件(UltraToolBarManager、UltraGird和UltraListView)进行扩展,...

24010
来自专栏java闲聊

SpringFlux入门(上篇)SpringBoot WebFlux

1593
来自专栏前端黑板报

(转)一探前端开发中的JS调试技巧

前言:调试技巧,在任何一项技术研发中都可谓是必不可少的技能。掌握各种调试技巧,必定能在工作中起到事半功倍的效果。譬如,快速定位问题、降低故障概率、帮助分析逻辑错...

1956
来自专栏大数据挖掘DT机器学习

Python]新手写爬虫全过程(已完成)

今天早上起来,第一件事情就是理一理今天该做的事情,瞬间get到任务,写一个只用python字符串内建函数的爬虫,定义为v1.0,开发中的版本号定义为v0.x。数...

3599
来自专栏君赏技术博客

GB代码规范1.0

对于如果导入是UIKit类就使用UIKIT_EXTERN 如果是Founction使用关键词FOUNDATION_EXTERN

952
来自专栏更流畅、简洁的软件开发方式

见到了“公司”定义一个Company类,那么见到了“字段”是不是也可定义一个Column类?

  既然见到了公司,我们可以定义一个Class Company ,那么我们见到了字段,是不是也可以定义一个Class ColumnInfo呢? 公司的描述信息类...

2339
来自专栏java一日一条

优化 iOS 程序性能的 25 个方法

ARC(Automatic ReferenceCounting, 自动引用计数)和iOS5一起发布,它避免了最常见的也就是经常是由于我们忘记释放内存所造成的内存...

773
来自专栏Linyb极客之路

web前端性能优化

网站的划分一般为二:前端和后台。我们可以理解成后台是用来实现网站的功能的,比如:实现用户注册,用户能够为文章发表评论等等。而前端呢?其实应该是属于功能的表现。并...

682
来自专栏青玉伏案

Objective-C中把数组中字典中的数据转换成URL

        可能上面的标题有些拗口,学过PHP的小伙伴们都知道,PHP中的数组的下标是允许我们自定义的,PHP中的数组确切的说就是键值对。而在OC我们要用字...

20510

扫码关注云+社区