项目需求需要对用户根据推荐人的不同进行树形结构显示.使用 tableView 实现这一需求.
实现思路
使用 tableView 实现先树形结构(不同的 cell 样式显示不同的等级),当点击 cell 时,判断当前点击的 cell 是否存在下一级,是否已经是打开状态.如果存在下一级,关闭状态,则通过插入 cell 实现点击展开树形图的效果.如果存在下一级且已经展开则通过删除 cell的方式实现树形图的关闭效果.
具体实现
- 定义数据结构类型,如下:
class YTTTreeListModel: NSObject {
/**
你所需要的属性
var name: String = ""
var address: String = ""
var age: Int = -1
...
**/
// 当前节点是否有下一级
var isShow: Bool = false
// 当前节点是否展开
var isOpen: Bool = false
// 当前的等级
var level: Int = 0
// 当前节点的子节点
var child: [QWMyTeamModel] = []
}
复制代码
- 定义主要的方法(递归算法)
/// 获取 cell 的行数
///
/// - Parameter items: 数据源
/// - Returns: cell 行数
private func getRowsNum(_ items: [YTTTreeListModel]) -> Int {
var num = 0
items.forEach { (model) in
num += 1
if model.isShow && model.isOpen && model.child.count > 0 {
num += getRowsNum(model.child)
}
}
return num
}
/// 获取当前 cell 的数据模型
///
/// - Parameters:
/// - items: 数据源
/// - index: 当前位置
/// - Returns: 数据模型
private func getItem(_ items: [YTTTreeListModel], index: inout Int) -> YTTTreeListModel? {
for item in items {
if index == 0 {
return item
}
index -= 1
if item.isShow && item.isOpen && item.child.count > 0 {
if let model = getItem(item.child, index: &index) {
return model
}
}
}
return nil
}
/// 获取需要添加或删除的 cell
///
/// - Parameters:
/// - item: 当前数据模型(点击的 cell)
/// - index: 当前位置
/// - Returns: 需要删除或添加位置
private func getIndexPath(_ item: YTTTreeListModel, index: inout Int) -> [IndexPath] {
var indexPaths: [IndexPath] = []
for item in item.child {
index += 1
indexPaths.append(IndexPath(row: index, section: 0))
if item.isShow && item.isOpen && item.child.count > 0 {
indexPaths.append(contentsOf: getIndexPath(item, index: &index))
}
}
return indexPaths
}
复制代码
- 实现代理方法
// dataArr private var dataArr: [YTTTreeListModel] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return getRowsNum(dataArr)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var index = indexPath.row
if let model = getItem(dataArr, index: &index) {
if model.level == 1 {
// 返回第一级样式
} else if model.level == 2 {
// 返回第二级样式
}else if model.level == 3 {
// 返回第三级样式
}
...
}
return UITableViewCell()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var index = indexPath.row
if let model = getItem(dataArr, index: &index) {
if model.isOpen {
tableView.beginUpdates()
model.isOpen = false
var ind = indexPath.row
tableView.reloadRows(at: [indexPath], with: .none)
tableView.deleteRows(at: getIndexPath(model, index: &ind), with: .none)
tableView.endUpdates()
}else {
if !model.isShow {
return
}
// 存在下一级且子级已经加载直接展开
if model.isShow == 1 && model.child.count > 0 {
tableView.beginUpdates()
model.isOpen = true
var ind = indexPath.row
tableView.reloadRows(at: [indexPath], with: .none)
tableView.insertRows(at: getIndexPath(model, index: &ind), with: .none)
tableView.endUpdates()
}else {
// 存在下一级,但数据未请 求网络请求
http.globalPOST(url: **, parameters: ["": ""], success: { [weak self] (result) in
if let models = YTTTreeListModel(dictArray: result) as? [YTTTreeListModel] {
model.child = models.compactMap({ (item) -> YTTTreeListModel in
item.level = model.level + 1 // 设置等级
return item
})
tableView.beginUpdates()
model.isOpen = true
var ind = indexPath.row
tableView.reloadRows(at: [indexPath], with: .none)
if let indexs = self?.getIndexPath(model, index: &ind) {
tableView.insertRows(at: indexs, with: .none)
}
tableView.endUpdates()
}
}, fail: {(error) in
}, isHUD: true)
}
}
}
}
复制代码