PickerView 三级联动

引言

最近公司有个需求, 要做一个PickerView三级联动的菜单, 要求实现可供用户选择未来24小时内任一时间点的功能, 最小可选单位为分. 其中第一列为今天或明天, 第二列为时, 第三列为分. 由于前列时间点的选择会影响后列时间点的可选范围, 这就涉及到联动问题. 网上的联动例子也有不少, 不过感觉大都是同一个例子, 都是说的城市, 而且只是二级联动(虽然三级联动也大同小异), 毕竟这个案例自己也是花了点心思, 希望大家可以赏面来看看, 如果有刚好要做类似功能的朋友, 也希望能对你们有所帮助. 这是最终效果图:

1.gif

正文

主要想就项目过程中遇到的几个点说一下自己的想法:

  1. 关于时间数据源
    这个问题确实有点恶心的, 第一列只要展示今天明天, 没问题;
    第二列问题也不太大, 就2组数据, 根据第一列的选择情况分别展示即可, 不过这里需要注意的是, 如果当前时间为59分时, 当前的时就不需要展示了, 因为第三列已经没有可供用户选择的范围了, 比如说现在是10时59分, 那么10时就不需要显示了, 应该直接跳到11时;
    最恶心的是第三列, 有3组数据, 需要根据前2列的选中状态来共同决定, 而且如果当前时间为59分时, 还要注意数据源的切换.

  2. 关于联动的崩溃
    这是个非常经典的问题, 网上很多地方也有说到, 几乎是做过联动的朋友都会遇到的, 就是在同时滑动2列数据的时候很容易出现数组访问越界的情况, 然后就悲剧了. 具体的原因是在数据源方法- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;①中使用了方法- (NSInteger)selectedRowInComponent:(NSInteger)component;②去获取当前所选元素的下标, 然后去对应的数组获取第row个下标的元素, 乍看之下感觉没什么问题, 这也是为什么这么多人都会遇到这个崩溃情况的原因, 那究竟是哪里出问题了呢? 原因在于代理方法- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;③的调用时机. 这个方法是在某列滚动停止后就会调用, 我们一般会在此方法中刷新对应其它列的数据, 实现联动功能. 那么问题来了, 上面的数据源方法调用的频率是很高的, 在滑动过程中会不停地调用, 冲突就来了.
    举个例子来说, 比如现在是20时30分, 当第一列选择今天时, 第二列的数据只有20-23这4个元素可选. 而当第一列选择明天时, 第二列的数据就多了, 有00-20共21个元素可选. 如果此时第一列选择明天, 第二列正在往下标大的元素方向滑动进行中, 然后第一列突然向今天滑去, 在滑到今天且准备停止时, 代理方法还未能调用, 也就是第二列的数据未能刷新数据源, 说白了就是未能重新走一次数据源方法- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;④来重新获取需要展示的元素个数, 也就是说进去数据源方法中的参数row还可以达到20这个下标, 而此时在数据源方法中调用方法获取第一列被选中的元素下标时却能获取到被选中的是今天这个下标, 也就是说会从20-23这4个元素中去拿值, 在只有4个元素的数组中取下标为20的值, 就造成崩溃了.
    可能说得有点乱, 简单来说就是方法是直接拿到当前被选中的元素下标, 而代理方法则是在某一列停止滚动时才会被调用, 所以这里出现了数据没匹对上的情况. 解决方法就是满足调用次数少的一方, 也就是增加全局属性来记录当前被选中的元素下标, 当然是在代理方法中进行更新赋值操作, 并且要在刷新其它列数据的命令之前(这里要补充一点的是, 由于是联动关系, 要注意做好递规处理和下一列的选中下标处理, 不然同样会造成数组越界问题), 取数据源时直接通过全局属性替换掉原来的用方法获取当前被选中元素下标的做法:

    2.png

    3.png

    4.png

  3. 输出所选结果
    来到这里其实已经没有什么问题了, 直接把整个结果输出.


    5.png

后记

其实在做这个案例时我还想到了其它奇奇怪怪的解决方案, 比如在数据源方法中刷新某一列的数据, 或者在数据源方法中输出结果等等, 不过这些做法都太影响性能了, 还有可能会产生其它BUG, 最后觉得还是目前这样的处理方法比较可行, 也希望大家有好的想法可以一起分享指正.

最后附上一个GitHub的Demo小示例, 谢谢大家~

https://github.com/Veeco/WG24HPicker

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容