The project needs to display the users in a tree structure according to the different referees. Use tableView to do this.
Implementation approach
Use tableView to realize the tree structure (different cell styles show different levels). When clicking the cell, judge whether the current clicked cell has the next level and whether it has been opened. If the next-level, off state exists, click to expand the tree by inserting the cell. If the next level exists and has been expanded, the tree graph can be closed by deleting cells.
The specific implementation
- Define the data structure type as follows:
class YTTTreeListModel: NSObject {
Var name: String = "" var address: String = "" var age: Int = -1... * * /
// Whether the current node has a next level
var isShow: Bool = false
// Whether the current node is expanded
var isOpen: Bool = false
// The current level
var level: Int = 0
// Children of the current node
var child: [QWMyTeamModel] = []}Copy the code
- Define the main method (recursive algorithm)
/// Get the number of cell lines
///
/// -parameter items: data source
/// - Returns: Number of cell rows
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
}
// get the data model of the current cell
///
/// - Parameters:
/// -items: data source
/// -index: indicates the current position
/// - Returns: data model
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
}
/// Obtain the cell to be added or deleted
///
/// - Parameters:
/// -item: current data model (click cell)
/// -index: indicates the current position
/// - Returns: A location needs to be deleted or added
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
}
Copy the code
- Implementing proxy methods
// 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 {
// returns the first level of style
} else if model.level == 2 {
// Returns the second-level style
}else if model.level == 3 {
// Return the third level style}... }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
}
// The next level exists and the children are already loaded
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 {
// The next level exists, but the data is not requested by the network
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 // Set the level
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)}}}}Copy the code