PickerView 三級(jí)聯(lián)動(dòng)

引言

最近公司有個(gè)需求, 要做一個(gè)PickerView三級(jí)聯(lián)動(dòng)的菜單, 要求實(shí)現(xiàn)可供用戶選擇未來(lái)24小時(shí)內(nèi)任一時(shí)間點(diǎn)的功能, 最小可選單位為分. 其中第一列為今天或明天, 第二列為時(shí), 第三列為分. 由于前列時(shí)間點(diǎn)的選擇會(huì)影響后列時(shí)間點(diǎn)的可選范圍, 這就涉及到聯(lián)動(dòng)問(wèn)題. 網(wǎng)上的聯(lián)動(dòng)例子也有不少, 不過(guò)感覺(jué)大都是同一個(gè)例子, 都是說(shuō)的城市, 而且只是二級(jí)聯(lián)動(dòng)(雖然三級(jí)聯(lián)動(dòng)也大同小異), 畢竟這個(gè)案例自己也是花了點(diǎn)心思, 希望大家可以賞面來(lái)看看, 如果有剛好要做類(lèi)似功能的朋友, 也希望能對(duì)你們有所幫助. 這是最終效果圖:

1.gif

正文

主要想就項(xiàng)目過(guò)程中遇到的幾個(gè)點(diǎn)說(shuō)一下自己的想法:

  1. 關(guān)于時(shí)間數(shù)據(jù)源
    這個(gè)問(wèn)題確實(shí)有點(diǎn)惡心的, 第一列只要展示今天明天, 沒(méi)問(wèn)題;
    第二列問(wèn)題也不太大, 就2組數(shù)據(jù), 根據(jù)第一列的選擇情況分別展示即可, 不過(guò)這里需要注意的是, 如果當(dāng)前時(shí)間為59分時(shí), 當(dāng)前的時(shí)就不需要展示了, 因?yàn)榈谌幸呀?jīng)沒(méi)有可供用戶選擇的范圍了, 比如說(shuō)現(xiàn)在是10時(shí)59分, 那么10時(shí)就不需要顯示了, 應(yīng)該直接跳到11時(shí);
    最?lèi)盒牡氖堑谌? 有3組數(shù)據(jù), 需要根據(jù)前2列的選中狀態(tài)來(lái)共同決定, 而且如果當(dāng)前時(shí)間為59分時(shí), 還要注意數(shù)據(jù)源的切換.

  2. 關(guān)于聯(lián)動(dòng)的崩潰
    這是個(gè)非常經(jīng)典的問(wèn)題, 網(wǎng)上很多地方也有說(shuō)到, 幾乎是做過(guò)聯(lián)動(dòng)的朋友都會(huì)遇到的, 就是在同時(shí)滑動(dòng)2列數(shù)據(jù)的時(shí)候很容易出現(xiàn)數(shù)組訪問(wèn)越界的情況, 然后就悲劇了. 具體的原因是在數(shù)據(jù)源方法- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;①中使用了方法- (NSInteger)selectedRowInComponent:(NSInteger)component;②去獲取當(dāng)前所選元素的下標(biāo), 然后去對(duì)應(yīng)的數(shù)組獲取第row個(gè)下標(biāo)的元素, 乍看之下感覺(jué)沒(méi)什么問(wèn)題, 這也是為什么這么多人都會(huì)遇到這個(gè)崩潰情況的原因, 那究竟是哪里出問(wèn)題了呢? 原因在于代理方法- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;③的調(diào)用時(shí)機(jī). 這個(gè)方法是在某列滾動(dòng)停止后就會(huì)調(diào)用, 我們一般會(huì)在此方法中刷新對(duì)應(yīng)其它列的數(shù)據(jù), 實(shí)現(xiàn)聯(lián)動(dòng)功能. 那么問(wèn)題來(lái)了, 上面的數(shù)據(jù)源方法調(diào)用的頻率是很高的, 在滑動(dòng)過(guò)程中會(huì)不停地調(diào)用, 沖突就來(lái)了.
    舉個(gè)例子來(lái)說(shuō), 比如現(xiàn)在是20時(shí)30分, 當(dāng)?shù)谝涣羞x擇今天時(shí), 第二列的數(shù)據(jù)只有20-23這4個(gè)元素可選. 而當(dāng)?shù)谝涣羞x擇明天時(shí), 第二列的數(shù)據(jù)就多了, 有00-20共21個(gè)元素可選. 如果此時(shí)第一列選擇明天, 第二列正在往下標(biāo)大的元素方向滑動(dòng)進(jìn)行中, 然后第一列突然向今天滑去, 在滑到今天且準(zhǔn)備停止時(shí), 代理方法還未能調(diào)用, 也就是第二列的數(shù)據(jù)未能刷新數(shù)據(jù)源, 說(shuō)白了就是未能重新走一次數(shù)據(jù)源方法- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;④來(lái)重新獲取需要展示的元素個(gè)數(shù), 也就是說(shuō)進(jìn)去數(shù)據(jù)源方法中的參數(shù)row還可以達(dá)到20這個(gè)下標(biāo), 而此時(shí)在數(shù)據(jù)源方法中調(diào)用方法獲取第一列被選中的元素下標(biāo)時(shí)卻能獲取到被選中的是今天這個(gè)下標(biāo), 也就是說(shuō)會(huì)從20-23這4個(gè)元素中去拿值, 在只有4個(gè)元素的數(shù)組中取下標(biāo)為20的值, 就造成崩潰了.
    可能說(shuō)得有點(diǎn)亂, 簡(jiǎn)單來(lái)說(shuō)就是方法是直接拿到當(dāng)前被選中的元素下標(biāo), 而代理方法則是在某一列停止?jié)L動(dòng)時(shí)才會(huì)被調(diào)用, 所以這里出現(xiàn)了數(shù)據(jù)沒(méi)匹對(duì)上的情況. 解決方法就是滿足調(diào)用次數(shù)少的一方, 也就是增加全局屬性來(lái)記錄當(dāng)前被選中的元素下標(biāo), 當(dāng)然是在代理方法中進(jìn)行更新賦值操作, 并且要在刷新其它列數(shù)據(jù)的命令之前(這里要補(bǔ)充一點(diǎn)的是, 由于是聯(lián)動(dòng)關(guān)系, 要注意做好遞規(guī)處理和下一列的選中下標(biāo)處理, 不然同樣會(huì)造成數(shù)組越界問(wèn)題), 取數(shù)據(jù)源時(shí)直接通過(guò)全局屬性替換掉原來(lái)的用方法獲取當(dāng)前被選中元素下標(biāo)的做法:

    2.png

    3.png

    4.png

  3. 輸出所選結(jié)果
    來(lái)到這里其實(shí)已經(jīng)沒(méi)有什么問(wèn)題了, 直接把整個(gè)結(jié)果輸出.


    5.png

后記

其實(shí)在做這個(gè)案例時(shí)我還想到了其它奇奇怪怪的解決方案, 比如在數(shù)據(jù)源方法中刷新某一列的數(shù)據(jù), 或者在數(shù)據(jù)源方法中輸出結(jié)果等等, 不過(guò)這些做法都太影響性能了, 還有可能會(huì)產(chǎn)生其它BUG, 最后覺(jué)得還是目前這樣的處理方法比較可行, 也希望大家有好的想法可以一起分享指正.

最后附上一個(gè)GitHub的Demo小示例, 謝謝大家~

https://github.com/Veeco/WG24HPicker

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市拥娄,隨后出現(xiàn)的幾起案子蚊锹,更是在濱河造成了極大的恐慌,老刑警劉巖稚瘾,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牡昆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡孟抗,警方通過(guò)查閱死者的電腦和手機(jī)迁杨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)凄硼,“玉大人铅协,你說(shuō)我怎么就攤上這事√粒” “怎么了狐史?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我骏全,道長(zhǎng)苍柏,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任姜贡,我火速辦了婚禮试吁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘楼咳。我一直安慰自己熄捍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布母怜。 她就那樣靜靜地躺著余耽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪苹熏。 梳的紋絲不亂的頭發(fā)上碟贾,一...
    開(kāi)封第一講書(shū)人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音轨域,去河邊找鬼袱耽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛疙挺,可吹牛的內(nèi)容都是我干的扛邑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼铐然,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蔬崩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起搀暑,我...
    開(kāi)封第一講書(shū)人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤沥阳,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后自点,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體桐罕,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年桂敛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了功炮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡术唬,死狀恐怖薪伏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情粗仓,我是刑警寧澤嫁怀,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布设捐,位于F島的核電站,受9級(jí)特大地震影響塘淑,放射性物質(zhì)發(fā)生泄漏萝招。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一存捺、第九天 我趴在偏房一處隱蔽的房頂上張望槐沼。 院中可真熱鬧,春花似錦召噩、人聲如沸母赵。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至师倔,卻和暖如春构韵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背趋艘。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工疲恢, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瓷胧。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓显拳,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親搓萧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子杂数,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容