UITableView实现树结构

//
//  ZKBaseTreeView.swift
//  TigeriotAppProject
//
//  Created by iOSDeveloper on 2025/5/22.
//

import UIKit




struct ZKBaseTreeNode: Hashable, Codable {

    var id: String?
    var treeNodeId: String?
    var parentId: String?
    var name: String?
    var entityType: String?
    var children: [ZKBaseTreeNode]?
    var isExpanded: Bool = false
    var isHalfSelect: Bool = false
    var canSelect: Bool = true
    var isSelected: Bool = false
    var depth: Int = 0
    var uuid: UUID = UUID()
    
    init(id: String?,
         treeNodeId: String?,
         parentId: String?,
         name: String?,
         children: [ZKBaseTreeNode]?,
         isExpanded: Bool = false,
         canSelect: Bool = true,
         isSelected: Bool = false,
         depth: Int = 0,
         uuid: UUID = UUID()) {
        
        self.id = id
        self.treeNodeId = treeNodeId
        self.parentId = parentId
        self.name = name
        self.children = children
        
        self.isExpanded = isExpanded
        self.canSelect = canSelect
        self.isSelected = isSelected
        self.depth = depth
        self.uuid = uuid
    }
    
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        isExpanded = try container.decodeIfPresent(Bool.self, forKey: .isExpanded) ?? false
        isHalfSelect = try container.decodeIfPresent(Bool.self, forKey: .isHalfSelect) ?? false
        canSelect = try container.decodeIfPresent(Bool.self, forKey: .canSelect) ?? true
        isSelected = try container.decodeIfPresent(Bool.self, forKey: .isSelected) ?? false
        depth = try container.decodeIfPresent(Int.self, forKey: .depth) ?? 0
        uuid = try container.decodeIfPresent(UUID.self, forKey: .uuid) ?? UUID()
        
        //-------------------------------------------------------------------//
        id = try container.decodeIfPresent(String.self, forKey: .id)
        name = try container.decodeIfPresent(String.self, forKey: .name)
        parentId = try container.decodeIfPresent(String.self, forKey: .parentId)
        treeNodeId = try container.decodeIfPresent(String.self, forKey: .treeNodeId)
        children = try container.decodeIfPresent([ZKBaseTreeNode].self, forKey: .children)
        entityType = try container.decodeIfPresent(String.self, forKey: .entityType)
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(treeNodeId)
        hasher.combine(parentId)
        hasher.combine(uuid)
    }
    
    static func == (lhs: ZKBaseTreeNode, rhs: ZKBaseTreeNode) -> Bool {
        lhs.treeNodeId == rhs.treeNodeId
    }
}

extension ZKBaseTreeNode {
    /// 深度优先遍历(DFS)方案
    /// - Returns: 返回一维平铺的结构
    func flattenedDFS() -> [ZKBaseTreeNode] {
        var result = [self]
        if let children = children, isExpanded {
            for child in children {
                result += child.flattenedDFS()
            }
        }
        return result
    }
    
    /// 深度优先遍历(DFS)方案,并计算深度
    /// - Returns: 返回一维平铺的结构
    func flattenedDFSWithDepth() -> [ZKBaseTreeNode] {
        var result = [self]
        if let children = children, isExpanded {
            for var child in children {
                child.depth = self.depth + 1
                result += child.flattenedDFSWithDepth()
            }
        }
        return result
    }
    
    
    /// 广度优先遍历(BFS)方案
    /// - Returns: 返回一维平铺的结构
    func flattenedBFS() -> [ZKBaseTreeNode] {
        var result = [self]
        var queue = children ?? []
        while !queue.isEmpty {
            let node = queue.removeFirst()
            result.append(node)
            if let children = node.children, node.isExpanded {
                queue.append(contentsOf: children)
            }
        }
        return result
    }
    
    /// 广度优先遍历(BFS)方案,并计算深度
    /// - Returns: 返回一维平铺的结构
    func flattenedBFSWithDepth() -> [ZKBaseTreeNode] {
        var result = [self]
        var queue: [(node: ZKBaseTreeNode, depth: Int)] = (children ?? []).map { ($0, 1) }
        while !queue.isEmpty {
            let (currentNode, currentDepth) = queue.removeFirst()
            // 更新当前节点的深度
            var nodeWithDepth = currentNode
            nodeWithDepth.depth = currentDepth
            result.append(nodeWithDepth)
            // 将子节点加入队列,深度+1
            if let children = currentNode.children, currentNode.isExpanded {
                queue.append(contentsOf: children.map { ($0, currentDepth + 1) })
            }
        }
        return result
    }
}


// 选择模式枚举
enum SelectionMode {
    case single
    case multiple
}

extension Array where Element == ZKBaseTreeNode {
    
    
    /// 更新节点选中状态(支持单选/多选和级联控制)
    /// - Parameters:
    ///   - targetNodes: 被点击的目标节点
    ///   - selectionMode: 选择模式(.single 或 .multiple)
    ///   - shouldCascade: 是否级联更新子节点和父节点状态
    /// - Returns: 更新后的树结构
    func updateSelection(for targetNodes: [ZKBaseTreeNode],selectionMode: SelectionMode = .single,shouldCascade: Bool = true) -> [ZKBaseTreeNode] {
        var newTree = self
            
        switch selectionMode {
        case .single:
            // 单选模式:先取消所有选中,再选中当前节点
            newTree.deselectAllNodes()
            guard let targetNode = targetNodes.first else { return newTree }
            newTree.toggleSingleSelection(for: targetNode)
        case .multiple:
            // 多选模式:切换所有目标节点的选中状态
            let targetIds = targetNodes.compactMap { $0.treeNodeId }
            newTree.toggleMultipleSelections(targetIds: targetIds)
        }
            
            // 级联更新子节点和父节点状态
        if shouldCascade {
            // 级联更新子节点
            for targetNode in targetNodes {
                newTree.setChildrenSelection(for: targetNode)
            }
            // 级联更新父节点状态
            newTree.refreshParentStatesWithPostOrder()
        }
        return newTree
    }
    
    
    /// 取消所有节点的选中状态
    mutating func deselectAllNodes() {
        for i in indices {
            self[i].isSelected = false
            self[i].isHalfSelect = false
            if var children = self[i].children {
                children.deselectAllNodes()
                self[i].children = children
            }
        }
    }
        
    /// 切换单个节点的选中状态(用于单选模式)
    mutating func toggleSingleSelection(for targetNode: ZKBaseTreeNode) {
        for i in indices {
            if self[i] == targetNode {
                self[i].isSelected = true
                self[i].isHalfSelect = false
                return
            }
            if var children = self[i].children {
                children.toggleSingleSelection(for: targetNode)
                self[i].children = children
            }
        }
    }
        
    // MARK: - 级联控制辅助方法
    /// 设置指定节点的所有子节点的选中状态(使用该节点当前的选中状态)
    mutating func setChildrenSelection(for targetNode: ZKBaseTreeNode) {
        for i in indices {
            if self[i] == targetNode {
                if var children = self[i].children {
                    children.setAllChildrenSelection(to: self[i].isSelected)
                    self[i].children = children
                }
                return
            }
            if var children = self[i].children {
                children.setChildrenSelection(for: targetNode)
                self[i].children = children
            }
        }
    }
}

extension Array where Element == ZKBaseTreeNode {
    
    ///平铺
    func flattened() -> [ZKBaseTreeNode] {
        var result = [ZKBaseTreeNode]()
        for node in self {
            result += node.flattenedDFSWithDepth()
        }
        return result
    }
    
    /// 更新节点展开状态并返回新树结构
    /// - Parameter targetNode: 被点击的目标节点
    /// - Returns: 更新后的完整树结构
    func updatingParentExpandedStates(for targetNode: ZKBaseTreeNode) -> [ZKBaseTreeNode] {
        var newTree = self
        let (found, shouldExpand) = newTree.toggleExpandedState(for: targetNode)
        if found && shouldExpand {
            newTree.expandPathToNode(targetNode)
        }
        return newTree
    }
    
    private mutating func toggleExpandedState(for targetNode: ZKBaseTreeNode) -> (Bool, Bool) {
        
        for i in 0..<self.count {
            if self[i] == targetNode {
                self[i].isExpanded.toggle()
                return (true, self[i].isExpanded)
            }
            if var children = self[i].children {
                let (found, shouldExpand) = children.toggleExpandedState(for: targetNode)
                if found {
                    self[i].children = children
                    if shouldExpand {
                        self[i].isExpanded = true
                    }
                    return (true, false)
                }
            }
        }
        return (false, false)
    }
    
    private mutating func expandPathToNode(_ targetNode: ZKBaseTreeNode) {
        for i in 0..<self.count {
            if self[i] == targetNode {
                return
            }
            if var children = self[i].children {
                //                let containsTargetBefore = children.contains { $0 == targetNode }
                // 递归展开子路径
                children.expandPathToNode(targetNode)
                // 检查递归后是否包含目标节点
                let containsTargetAfter = children.contains { $0 == targetNode }
                // 如果子节点包含目标节点,确保当前节点展开
                if containsTargetAfter {
                    self[i].isExpanded = true
                }
                self[i].children = children
            }
        }
    }
    
    /// 恢复节点展开状态(支持展开整棵子树)
    func recoveryExpandedStates(for targetNodes: [ZKBaseTreeNode], selectionMode: SelectionMode = .single, shouldCascade: Bool = true) -> [ZKBaseTreeNode] {
        var newTree = self
        for node in targetNodes {
            newTree.expandNodeAndChildren(for: node, selectionMode: selectionMode, shouldCascade: shouldCascade)
        }
        return newTree
    }
        
    /// 递归展开目标节点及其所有子节点
    @discardableResult private mutating func expandNodeAndChildren(for targetNode: ZKBaseTreeNode, selectionMode: SelectionMode = .single, shouldCascade: Bool = true) -> Bool {
        var found = false
        for i in 0..<self.count {
            // 匹配目标节点
            if self[i] == targetNode {
                found = true
                
                if selectionMode == .single && !shouldCascade {
                    
                } else {
                    // 展开当前节点
                    self[i].isExpanded = true
                    // 递归展开所有子节点
                    if var children = self[i].children {
                        children.expandAllChildren()
                        self[i].children = children
                    }
                }
            }
            
            // 递归查找目标节点
            if var children = self[i].children {
                if children.expandNodeAndChildren(for: targetNode, selectionMode: selectionMode, shouldCascade: shouldCascade) {
                    // 确保父节点展开以显示路径
                    self[i].isExpanded = true
                    found = true
                }
                self[i].children = children
            }
        }
        return found
        
    }
        
    /// 展开所有子节点(深度优先)
    private mutating func expandAllChildren() {
        for i in 0..<self.count {
            self[i].isExpanded = true
            if var children = self[i].children {
                children.expandAllChildren()
                self[i].children = children
            }
        }
    }
    
    /// 更新节点选中状态(级联模式,不依赖 parentId)
    /// 更新节点选中状态(支持同链路多节点操作)
    /// - Parameter targetNode: 被点击的目标节点
    /// - Returns: 更新后的树结构
    /*
    func updateSelection(for targetNodes: [ZKCustomTreeNode]) -> [ZKCustomTreeNode] {
        var newTree = self
        // 1. 批量切换目标节点状态(不立即返回)
        let targetIds = targetNodes.compactMap { $0.treeNodeId }
        newTree.toggleMultipleSelections(targetIds: targetIds)
        // 2. 统一更新所有父节点状态
        newTree.refreshParentStatesWithPostOrder()
        return newTree
    }
    */
    
    // MARK: - 改进的递归切换逻辑
    private mutating func toggleMultipleSelections(targetIds: [String]) {
        guard !targetIds.isEmpty else { return }
        for i in 0..<self.count {
            var needUpdateChildren = false
            // 检查当前节点是否需要切换状态
            if targetIds.contains(self[i].treeNodeId ?? "") {
                let newState = !self[i].isSelected
                self[i].isSelected = newState
                self[i].isHalfSelect = false
                needUpdateChildren = true
            }
            // 递归处理子节点(无论当前节点是否匹配都继续)
            if var children = self[i].children {
                children.toggleMultipleSelections(targetIds: targetIds)
                self[i].children = children
            }
            // 级联更新子节点状态
            if needUpdateChildren, var children = self[i].children {
                children.setAllChildrenSelection(to: self[i].isSelected)
                self[i].children = children
            }
        }
    }
    
    // MARK: - 改进的状态更新逻辑
    private mutating func refreshParentStatesWithPostOrder() {
        // 先处理子节点
        for i in 0..<self.count {
            if var children = self[i].children {
                children.refreshParentStatesWithPostOrder()
                self[i].children = children
            }
        }
        // 再处理当前节点
        self.updateNodeState()
    }
    
    private mutating func updateNodeState() {
        
        for i in 0..<self.count {
            guard let children = self[i].children, !children.isEmpty else {
                self[i].isHalfSelect = false
                continue
            }
            // 计算子节点状态
            var selectedCount = 0
            var hasPartial = false
            var hasUnselected = false
            
            for child in children {
                if child.isSelected { selectedCount += 1 }
                if child.isHalfSelect { hasPartial = true }
                if !child.isSelected { hasUnselected = true }
            }
            // 更新当前节点状态
            self[i].isSelected = (selectedCount == children.count) && !hasPartial
            self[i].isHalfSelect = hasPartial || (selectedCount > 0 && hasUnselected)
        }
    }

    // MARK: - 优化的子节点设置方法
    private mutating func setAllChildrenSelection(to isSelected: Bool) {
        for i in 0..<self.count {
            // 只修改子节点的选中状态,不修改展开状态
            self[i].isSelected = isSelected
            self[i].isHalfSelect = false
            if var children = self[i].children {
                children.setAllChildrenSelection(to: isSelected)
                self[i].children = children
            }
        }
    }
    
    /// 获取所有选中节点(包含子节点中的选中项)
    func selectedNodes() -> [ZKBaseTreeNode] {
        var result = [ZKBaseTreeNode]()
        self.traverse { node in
            if node.isSelected {
                result.append(node)
            }
        }
        return result
    }
    
    /// 递归遍历所有节点(深度优先遍历)
    private func traverse(_ action: (ZKBaseTreeNode) -> Void) {
        for node in self {
            action(node)
            if let children = node.children {
                children.traverse(action)
            }
        }
    }
    
}


class ZKBaseTreeCell: UITableViewCell {
    
    //左侧stackView
    private lazy var leftStackView: UIStackView = {
        let leftStackView = UIStackView()
        leftStackView.axis = .horizontal
        leftStackView.alignment = .center
        leftStackView.spacing = 8
        self.contentView.addSubview(leftStackView)
        return leftStackView
    }()
    
    //选择按钮
    private lazy var check: UIButton = {
        let check = UIButton()
        check.setImage(UIImage(named: "tree_check_unselect")?.withTintColor(UIColor(hex: AppThemeUtil.getcolor(themeEnum: .color_text_secondary)) ?? UIColor.text_color_tertiary, renderingMode: .alwaysOriginal), for: .normal)
        check.setImage(UIImage(named: "tree_check_half")?.withTintColor(UIColor(hex: AppThemeUtil.getcolor(themeEnum: .color_active)) ?? UIColor.normal_r, renderingMode: .alwaysOriginal), for: .highlighted)
        check.setImage(UIImage(named: "tree_check_select")?.withTintColor(UIColor(hex: AppThemeUtil.getcolor(themeEnum: .color_active)) ?? UIColor.normal_r, renderingMode: .alwaysOriginal), for: .selected)
        check.addTarget(self, action: #selector(checkClick), for: .touchUpInside)
        return check
    }()
    
    //树节点图标
    private lazy var icon: UIButton = {
        let icon = UIButton()
        icon.isUserInteractionEnabled = false
        icon.setImage(UIImage(named: "c_expand")?.withRenderingMode(.alwaysTemplate), for: .normal)
        icon.setImage(UIImage(named: "c_select_expand")?.withRenderingMode(.alwaysTemplate), for: .selected)
        icon.tintColor = UIColor(hex: AppThemeUtil.getcolor(themeEnum: .color_text_secondary))
        self.contentView.addSubview(icon)
        return icon
    }()
    
    //节点标题头图片
    private lazy var headImageView: UIImageView = {
        let headImageView = UIImageView()
        containerView.addSubview(headImageView)
        return headImageView
    }()
    
    //树标题
    private lazy var titleLabel: UILabel = {
        let titleLabel = UILabel()
        titleLabel.font = UIFont.small
        titleLabel.textColor = UIColor(hex: AppThemeUtil.getcolor(themeEnum: .color_text_primary))
        containerView.addSubview(titleLabel)
        return titleLabel
    }()
    
    private lazy var containerView: UIView = {
        let containerView = UIView()
        return containerView
    }()
    
    private lazy var containerButton: UIButton = {
        let containerButton = UIButton()
        containerButton.addTarget(self, action: #selector(buttonClick), for: .touchUpInside)
        containerView.addSubview(containerButton)
        return containerButton
    }()
    
    var buttonBlock: (() -> Void)?
    var checkClickBlock: (() -> Void)?
    
    
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        drawCellThemeColor()
        setupViews()
        setupConstraints()
    }
    
    func setTitleLabel(title: String?) {
        
        titleLabel.text = title
    }
    
    //更新树节点中图片文字颜色
    func updateColor(color: UIColor?) {
        if let color = color {
            headImageView.tintColor = color
            titleLabel.textColor = color
        } else {
            headImageView.tintColor = UIColor(hex: AppThemeUtil.getcolor(themeEnum: .color_text_primary))
            titleLabel.textColor = UIColor(hex: AppThemeUtil.getcolor(themeEnum: .color_text_primary))
        }
    }
    
    func updateDepth(depth: Int) {
        let offsetValue: CGFloat = CGFloat(depth) * 20
        headImageView.snp.remakeConstraints { make in
            make.left.equalTo(offsetValue)
            make.width.height.equalTo(20)
            make.centerY.equalToSuperview()
        }
    }
    
    func updateCheck(hidden: Bool) {
        check.isHidden = hidden
    }
    
    func updateHeadImage(image: UIImage?) {
        headImageView.image = image?.withRenderingMode(.alwaysTemplate)
        headImageView.tintColor = UIColor(hex: AppThemeUtil.getcolor(themeEnum: .color_text_primary))
    }
    
    func updateIcon(hidden: Bool) {
        icon.isHidden = hidden
    }
    
    func updateExpanded(expand: Bool) {
        if expand {
            icon.isSelected = true
        } else {
            icon.isSelected = false
        }
    }
    
    func updateSelected(selected: Bool, halfSelect: Bool) {
        
        if selected {
            check.isHighlighted = false
            check.isSelected = true
        } else if halfSelect {
            check.isHighlighted = true
            check.isSelected = false
        } else {
            check.isHighlighted = false
            check.isSelected = false
        }
    }
    
    
    private func setupViews() {
        self.selectionStyle = .none
        leftStackView.addArrangedSubview(check)
        leftStackView.addArrangedSubview(containerView)
    }
    
    private func setupConstraints() {
        
        leftStackView.snp.remakeConstraints { make in
            make.left.equalTo(8)
            make.height.equalTo(44)
            make.centerY.equalToSuperview()
        }
        
        check.snp.remakeConstraints { make in
            make.width.equalTo(30)
            make.height.equalTo(30)
        }
       
        containerView.snp.remakeConstraints { make in
            make.height.equalTo(30)
        }
        
        headImageView.snp.remakeConstraints { make in
            make.left.equalTo(0)
            make.width.height.equalTo(16)
            make.centerY.equalToSuperview()
        }
        
        titleLabel.snp.remakeConstraints { make in
            make.left.equalTo(headImageView.snp.right).offset(5)
            make.centerY.equalToSuperview()
            make.right.equalTo(0)
        }
        
        containerButton.snp.remakeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        icon.snp.remakeConstraints { make in
            make.right.equalTo(-5)
            make.width.height.equalTo(15)
            make.centerY.equalToSuperview()
        }
    }
    
    
    @objc func buttonClick() {
        
        buttonBlock?()
    }
    
    @objc func checkClick() {
        
        checkClickBlock?()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }
    
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        
        // Configure the view for the selected state
    }
}


class ZKBaseTreeView: UIView {
    
    
    var trees = [ZKBaseTreeNode]()
    
    enum Section: Hashable {
        case main
    }
    
    var dataSource: UITableViewDiffableDataSource<Section, ZKBaseTreeNode>!
    
    lazy var treeTableView: UITableView = {
        
        let treeTableView = UITableView(frame: .zero, style: .insetGrouped)
        treeTableView.backgroundColor = UIColor.clear
        treeTableView.sectionHeaderHeight = 0
        treeTableView.sectionFooterHeight = 0
        treeTableView.estimatedSectionHeaderHeight = 0
        treeTableView.estimatedSectionFooterHeight = 0
        treeTableView.delegate = self
        treeTableView.register(ZKBaseTreeCell.self, forCellReuseIdentifier: "ZKBaseTreeCell")
        self.addSubview(treeTableView)
        return treeTableView
        
    }()
    
    
    var selectNodes = [ZKBaseTreeNode]()
    var updateSelectBlock: (([ZKBaseTreeNode]) -> Void)?
    var selectionMode: SelectionMode = .single
    var shouldCascade: Bool = false
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = UIColor.clear
        
        setupUI()
        configureDataSource()
        updateExpandedStates()
        applyInitialSnapshot()
    }
    
    
    func setTreeData(datas: [ZKBaseTreeNode]) {
        trees = datas
        if selectNodes.count > 0 {
            updateExpandedStates()
            selectNodes = trees.selectedNodes()
            updateSelectBlock?(selectNodes)
        }
        
        applyInitialSnapshot()
    }
    
    
    private func setupUI() {
        treeTableView.snp.remakeConstraints { make in
            make.edges.equalToSuperview()
        }
    }
    
    
    func configureDataSource() {
        
        dataSource = UITableViewDiffableDataSource(tableView: treeTableView, cellProvider: { [weak self] tableView, indexPath, itemIdentifier in
           
            let cell: ZKBaseTreeCell = tableView.dequeueReusableCell(withIdentifier: "ZKBaseTreeCell", for: indexPath) as! ZKBaseTreeCell
            guard let `self` = self else { return cell }
            cell.setTitleLabel(title: itemIdentifier.name)
            cell.updateDepth(depth: itemIdentifier.depth)
            cell.updateHeadImage(image: CustomTreeTool.getTreeNodeImage(type: itemIdentifier.entityType))
            cell.updateSelected(selected: itemIdentifier.isSelected, halfSelect: itemIdentifier.isHalfSelect)
            cell.updateIcon(hidden: itemIdentifier.children?.count == 0)
            cell.updateExpanded(expand: itemIdentifier.isExpanded)
            
            cell.checkClickBlock = { [weak self] in
                guard let `self` = self else { return }
                trees = trees.updateSelection(for: [itemIdentifier], selectionMode: selectionMode, shouldCascade: shouldCascade)
                updateSnapshot()
                selectNodes = trees.selectedNodes()
                updateSelectBlock?(selectNodes)
            }
            return cell
        })
    }
    
    private func updateExpandedStates() {
        
        trees = trees.recoveryExpandedStates(for: selectNodes, selectionMode: selectionMode, shouldCascade: shouldCascade)
        trees = trees.updateSelection(for: selectNodes, selectionMode: selectionMode, shouldCascade: shouldCascade)
    }
    
    func applyInitialSnapshot() {
        var snapshot = NSDiffableDataSourceSnapshot<Section, ZKBaseTreeNode>()
        snapshot.appendSections([.main])
        let items = trees.flattened()
        snapshot.appendItems(items, toSection: .main)
        dataSource.apply(snapshot, animatingDifferences: false)
    }
    
    func updateSnapshot(animated: Bool = false) {
        applyInitialSnapshot()
        treeTableView.visibleCells.forEach { cell in
            let cell: ZKBaseTreeCell = cell as! ZKBaseTreeCell
            if let indexPath = treeTableView.indexPath(for: cell) {
                if let item = dataSource.itemIdentifier(for: indexPath) {
                    cell.setTitleLabel(title: item.name)
                    cell.updateDepth(depth: item.depth)
                    cell.updateHeadImage(image: CustomTreeTool.getTreeNodeImage(type: item.entityType))
                    cell.updateSelected(selected: item.isSelected, halfSelect: item.isHalfSelect)
                    cell.updateIcon(hidden: item.children?.count == 0)
                    cell.updateExpanded(expand: item.isExpanded)
                }
            }
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}


extension ZKBaseTreeView: UITableViewDelegate {
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        guard let item = dataSource.itemIdentifier(for: indexPath) else { return }
        trees = trees.updatingParentExpandedStates(for: item)
        updateSnapshot()
    }
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return CGFloat.leastNormalMagnitude
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 44
    }
    
}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容