iOS多級(jí)列表實(shí)現(xiàn)代碼
在項(xiàng)目開發(fā)中,層級(jí)列表經(jīng)常遇到,簡(jiǎn)單點(diǎn)的二級(jí)列表利用UITableView的Header就可以實(shí)現(xiàn),再簡(jiǎn)單點(diǎn)的三級(jí)列表通過(guò)對(duì)Cell高度進(jìn)行調(diào)整也可以實(shí)現(xiàn)三級(jí)列表的效果。但遇到多級(jí)列表,尤其是層次不明的動(dòng)態(tài)列表就比較麻煩了。
原理
層級(jí)列表和樹形結(jié)構(gòu)比較類似,不過(guò)不是二叉樹,而是多叉樹。每個(gè)節(jié)點(diǎn)只需要擁有指向父節(jié)點(diǎn)和子節(jié)點(diǎn)的兩個(gè)指針,就能形成一顆樹。我們將多級(jí)列表中每一級(jí)對(duì)象看作一個(gè)node,node擁有兩個(gè)屬性,分別為父節(jié)點(diǎn)和子節(jié)點(diǎn)的ID。
每棵樹有個(gè)一個(gè)虛擬的root節(jié)點(diǎn),它的ID為rootID,所有節(jié)點(diǎn)中凡是父節(jié)點(diǎn)ID為rootID的便是第一級(jí),對(duì)應(yīng)樹結(jié)構(gòu)中的depth(深度)。這樣每一個(gè)node對(duì)象就都擁有了parentID和childrenID, childrenID為node對(duì)象的ID。
我們可以通過(guò)rootID查出第一級(jí)node,再根據(jù)第一級(jí)node的childrenID查出下一級(jí),依次類推,確定所有節(jié)點(diǎn)的父子關(guān)系。同時(shí)也可以確定葉子節(jié)點(diǎn)和第一級(jí)節(jié)點(diǎn),也可稱
為根節(jié)點(diǎn)。
效果圖
1.一般多級(jí)列表
2.記錄節(jié)點(diǎn)歷史狀態(tài)的列表
思路
1.首先根據(jù) rootID 獲取所有第一級(jí)節(jié)點(diǎn),并放入U(xiǎn)ITableView的數(shù)據(jù)源 dataSourceArr 中,展示初始化列表
2. 展開: 點(diǎn)擊節(jié)點(diǎn)cell,根據(jù) childrenID 查找下一級(jí)nodes,并插入到 dataSourceArr 中currentNode的后面,刷新展示
3. 收攏: 點(diǎn)擊以打開節(jié)點(diǎn)cell,從 dataSourceArr 的CurrentIndex+1開始,如果該節(jié)點(diǎn)的level小于currentNode的level,則移除node,否則停止刷新列表。
4.點(diǎn)擊cell為葉子節(jié)點(diǎn)則不響應(yīng)展開或收攏操作,并把節(jié)點(diǎn)信息通過(guò)返回。
dataSourceArr中是這樣的一種符合樹層級(jí)結(jié)構(gòu)的順序:
定義節(jié)點(diǎn)對(duì)象
遇到問(wèn)題
1.局部刷新的問(wèn)題
每次展開或收攏以后刷新列表,一開始采用
但會(huì)導(dǎo)致節(jié)目有整體閃爍的效果,體驗(yàn)不好。最后考慮采用局部刷新 insertRowsAtIndexPaths 和 deleteRowsAtIndexPaths 。
但在刷新中會(huì)報(bào)錯(cuò)
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete row 2 from section 0 which only contains 2 rows before the update'
推測(cè)原因是 current Cell在刷新時(shí)的numberOfRowsInSection和刷新insert or del的cell時(shí)numberOfRowsInSection不一致導(dǎo)致 。然后嘗試current cell和其他cell分別刷新,完美刷新。
[_reloadArray removeAllObjects]; [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; if (currentNode.isExpand) { //expand [self expandNodesForParentID:currentNode.childrenID insertIndex:indexPath.row]; [tableView insertRowsAtIndexPaths:_reloadArray withRowAnimation:UITableViewRowAnimationNone]; }else{ //fold [self foldNodesForLevel:currentNode.level currentIndex:indexPath.row]; [tableView deleteRowsAtIndexPaths:_reloadArray withRowAnimation:UITableViewRowAnimationNone]; }
2.怎么保存節(jié)點(diǎn)歷史狀態(tài)
當(dāng)文件級(jí)層比較多時(shí),有時(shí)希望能關(guān)掉層級(jí)后再打開時(shí)還能保留子層級(jí)的打開狀態(tài)。我們可以會(huì)給每一個(gè)node一個(gè)是否展開的屬性,當(dāng)fold時(shí)只修改currentNode的expand屬性,expand時(shí)對(duì)子節(jié)點(diǎn)序isexpand=Y(jié)ES的進(jìn)行遍歷插入。
//expand - (NSUInteger)expandNodesForParentID:(NSString*)parentID insertIndex:(NSUInteger)insertIndex{ for (int i = 0 ; i<_nodes.count;i++) { YKNodeModel *node = _nodes[i]; if ([node.parentID isEqualToString:parentID]) { if (!self.isPreservation) { node.expand = NO; } insertIndex++; [_tempNodes insertObject:node atIndex:insertIndex]; [_reloadArray addObject:[NSIndexPath indexPathForRow:insertIndex inSection:0]];//need reload nodes if (node.isExpand) { insertIndex = [self expandNodesForParentID:node.childrenID insertIndex:insertIndex]; } } } return insertIndex; }
demo地址:
https://github.com/YangKa/YKMutableLevelTableView.git
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- IOS實(shí)現(xiàn)展開二級(jí)列表效果
- IOS展開三級(jí)列表效果示例
- IOS實(shí)現(xiàn)簡(jiǎn)易版的QQ下拉列表
- iOS開發(fā)之在列表上方添加水印的方法
- iOS 標(biāo)簽Tag列表的實(shí)現(xiàn)代碼
- ios基于UITableViewController實(shí)現(xiàn)列表
- iOS實(shí)現(xiàn)列表折疊效果
- iOS列表上拉(平滑加載數(shù)據(jù))自動(dòng)加載數(shù)據(jù)的問(wèn)題解決
- iOS實(shí)現(xiàn)從通訊錄中選擇聯(lián)系人
- iOS實(shí)現(xiàn)聯(lián)系人列表功能
相關(guān)文章
iOS開發(fā)中不合法的網(wǎng)絡(luò)請(qǐng)求地址如何解決
這篇文章主要介紹了iOS開發(fā)中不合法的網(wǎng)絡(luò)請(qǐng)求地址的解決方案,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09iOS 本地視頻和網(wǎng)絡(luò)視頻流播放實(shí)例代碼
本篇文章主要介紹了iOS 本地視頻和網(wǎng)絡(luò)視頻流播放實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07iOS開發(fā)中使用UIScrollView實(shí)現(xiàn)圖片輪播和點(diǎn)擊加載
這篇文章主要介紹了iOS開發(fā)中使用UIScrollView實(shí)現(xiàn)圖片輪播和點(diǎn)擊加載的方法,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-12-12iOS App開發(fā)中修改UILabel默認(rèn)字體的方法
UILabel是控制字體顯示的主要方式,這里我們就來(lái)看看通過(guò)NSAttributedText和NSMutableAttributedText這兩個(gè)類或者用runtime的方式來(lái)在iOS App開發(fā)中修改UILabel默認(rèn)字體的方法2016-07-07iOS優(yōu)化UITableViewCell高度計(jì)算的一些事兒
這iOS開發(fā)中對(duì)于UITableViewCell高度自適應(yīng)的文章已經(jīng)很多很多,但都不是自己所需要的,下面篇文章主要給大家介紹了關(guān)于iOS優(yōu)化UITableViewCell高度計(jì)算的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-11-11IOS Swift 開發(fā)QRCore(二維碼)實(shí)例詳解
這篇文章主要介紹了IOS Swift 開發(fā)QRCore(二維碼)實(shí)例詳解的相關(guān)資料,這里對(duì)開發(fā)二維碼進(jìn)行了詳細(xì)介紹,需要的朋友可以參考下2016-12-12iOS實(shí)現(xiàn)獲取系統(tǒng)iTunes音樂(lè)的方法示例
這篇文章主要給大家介紹了關(guān)于iOS如何實(shí)現(xiàn)獲取系統(tǒng)iTunes音樂(lè)的相關(guān)資料,文中通過(guò)示例代碼給大家詳細(xì)介紹了實(shí)現(xiàn)的方法,并給大家介紹了MPMediaPickerController的相關(guān)知識(shí),對(duì)大家的學(xué)習(xí)或者工作具有一定的幫助,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11iOS中使用UISearchBar控件限制輸入字?jǐn)?shù)的實(shí)現(xiàn)方法
這篇文章主要介紹了iOS中使用UISearchBar控件限制輸入字?jǐn)?shù)的實(shí)現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下2016-08-08