iOS實(shí)踐:打造一個(gè)可以快速索引的城市列表頁

相信絕大部分LBS的APP里面,大家都能看到一個(gè)帶索引的城市列表頁面,用來讓用戶選擇所在城市。

我們就一步一步的來實(shí)現(xiàn)這個(gè)頁面,最終效果如下:

Paste_Image.png

最終我們會(huì)按照首字母漢語拼音對所有城市進(jìn)行排序,可以通過右側(cè)的首字母索引來快速定位到城市。

1. 從plist中獲取城市字典

1.1 準(zhǔn)備素材,下載文件

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

鏈接: 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

  • 字典中有一個(gè)屬性allKeys,可以取出字典中所有的key。這是一個(gè)只讀的屬性。
  • 根據(jù)allKeys就能知道字典中有多少組,去對應(yīng)的數(shù)據(jù)源設(shè)置返回?cái)?shù)據(jù)。
@property (readonly, copy) NSArray<KeyType> *allKeys;

2. 對城市的首字母進(jìn)行排序

  • 對所有字典key的數(shù)組中的內(nèi)容進(jìn)行排序
  • 對于排序,系統(tǒng)提供了兩種辦法可以進(jìn)行排序。我們就不用再寫什么冒泡兒、選擇之類的算法了,直接來就可以用。

2.1 方法一:使用方法進(jìn)行排序:升序

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

2.2 使用block進(jìn)行排序:可以選擇排序的方法

    _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比較都進(jìn)行了一次排序。排序結(jié)果記錄在了NSComparisonReuslt中。
  • NSComparisonReuslt是一個(gè)枚舉。通過操作兩數(shù)比較的結(jié)果,進(jìn)行排序。如果兩數(shù)比較的結(jié)果一會(huì)兒是-1,一會(huì)兒是0,一會(huì)兒是1,那排序出來的結(jié)果也就是亂的。

官方對此說明:

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

3. 設(shè)置邊欄索引

  • 邊欄的索引顯示的文字和實(shí)際跳轉(zhuǎn)沒有直接關(guān)系。
  • 邊欄索引無論寫什么,都是按照實(shí)際的key值進(jìn)行跳轉(zhuǎn)的。
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView{
    return _firstLetterOfCitys;
}

4. 關(guān)于約束的重要提示

  • 所有的類方法在執(zhí)行初始化的時(shí)候都需要先去看看類里面初始化的方法首選項(xiàng)。

以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;

官方說明的意思是說,當(dāng)執(zhí)行init的時(shí)候,系統(tǒng)要求執(zhí)行了兩個(gè)初始化方法。

問題來了:如果在初始化的時(shí)候,寫成了[[UITableView alloc] init],在編譯的時(shí)候?qū)嶋H上還是執(zhí)行了兩個(gè)初始化方法。第一個(gè)初始化方法中要求傳入frame,此時(shí)因?yàn)闆]有傳入?yún)?shù),frame就會(huì)被默認(rèn)為{0.0.0.0}。

為了解決這個(gè)問題,當(dāng)view有了frame之后,就需要重新給tableView設(shè)置frame。是用以下方法進(jìn)行設(shè)置:

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

5. 完善:封裝

因?yàn)槌鞘辛斜斫窈笪覀兒苡锌赡軙?huì)在其他項(xiàng)目里面使用,但我們又不確定以后再使用的時(shí)候是用StoryBoard調(diào)用還是代碼調(diào)用。所以我們還要進(jìn)一步處理一下。

//當(dāng)從XIB或者UIStoryboard中創(chuàng)建UITableView的時(shí)候加載此方法
- (void)awakeFromNib{
    [super awakeFromNib];
    [self createCityListTableView];
}

//使用代碼創(chuàng)建的時(shí)候加載此方法
- (instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        [self createCityListTableView];
    }
    
    return self;
}

這樣就算是封裝好了,以后不管是SB還是代碼方式,都可以直接的把剛才寫好的城市列表進(jìn)行引用了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,534評論 19 139
  • 引子 對于一條SQL,開發(fā)同學(xué)最先關(guān)心的啥? 我覺得還不到這個(gè)SQL在數(shù)據(jù)庫的執(zhí)行過程,而是這條SQL是否能盡快的...
    大頭8086閱讀 2,733評論 2 14
  • 如果你從來沒有成為誰的first choice 是不是很悲涼。 有些人走著走著就淡了。
    秋蕙閱讀 173評論 0 0
  • 每當(dāng)我無所事事,貪圖享樂的時(shí)候,我就會(huì)想起那張泛黃的信紙上你寫的那一句:做最好的自己。 你,是我心里不曾忘記的朋友...
    漠曉閱讀 247評論 3 2
  • 上一篇中,我只用了Retrofit,這篇加入了RxJava,進(jìn)行一個(gè)封裝,不知道RxJava是什么的同學(xué)可以去網(wǎng)上...
    ReturnYHH閱讀 663評論 1 1

友情鏈接更多精彩內(nèi)容