在程序开发过程中,常会遇到多级数据结构的显示,大多数情况下都是二级或三级的情况,这时候用UITableview的基本用法就可以解决此类问题。但是,有时候后若是有四级五级...,普通的使用方法就不是好了,之前我就遇到过了很多级的数据结构显示问题,在这里记录一下
因为我的数据量不是很大,才这样弄的,至于数据过大过多是,大家还是自己看着用吧😂
我这里还是用的UITableview,显示的问题是通过对数据本身的操作来完成,简而言之就是在数据中添加一个标记(type:用于显示其结构等级),然后在cell中根据该标记(type),做出相应的显示以区别。
由于显示的数据类型有很多,为避免在多个model中重复书写相同逻辑代码,也为了使用其通用性更好,我使用了协议的方式,下边是我的主要代码
import Foundation
///用于构造多级树
@objc protocol HZJTreeViewModelProtocol {
/// 所属父数据(不用手动去设置,会根据setChildModels自动修改)
var fatherModel:HZJTreeViewModelProtocol? { get set }
/// 包含的子数据(需使用setChildModels方法赋值)
var childModels:[HZJTreeViewModelProtocol] { get set }
}
//MARK: - 添加的非私有属性
extension HZJTreeViewModelProtocol {
/// 是否展示当前项
public var isShowCurrent:Bool {
return self._isShow
}
/// 是否打开,以展示当前项的childModels
public var isOpen:Bool {
return self._isOpen
}
///等级
var type:Int{
return self._type
}
}
//MARK: -用于修改属性的方法
extension HZJTreeViewModelProtocol {
@discardableResult
public func toShowCurrent(_ show:Bool) -> HZJTreeViewModelProtocol{
self._isShow = show
return self
}
@discardableResult
public func setOpenState(_ open:Bool) -> HZJTreeViewModelProtocol{
self._isOpen = open
return self
}
}
//MARK: -其他重要的方法
extension HZJTreeViewModelProtocol {
/// 设置子数据(注意不要循环引用了)
/// - Parameter models: <#models description#>
/// - Returns: <#description#>
@discardableResult
public func setChildModels(_ models:[HZJTreeViewModelProtocol]) -> [HZJTreeViewModelProtocol] {
for item in models {
item.fatherModel = self
item._isShow = self.isOpen
}
self.childModels = models
self.setAllChildModeType(self._type)
return self.childModels
}
/// 修改当前childModels的展示状态
/// - Parameter open: 是否展示
/// - Parameter allChild: 是否针对所有子数据
public func changeChildModelShowState(_ open:Bool, allChild:Bool = false) {
self._isOpen = open
for item in self.childModels {
item._isShow = open
if allChild {
item.changeChildModelShowState(open, allChild: allChild)
}
}
}
/// 获取所有子数据(包括子数据的子数据的子数据...递归操作)
/// - Returns: <#description#>
public func getAllChildModel() -> [HZJTreeViewModelProtocol] {
var result:[HZJTreeViewModelProtocol] = []
for item in self.childModels {
result.append(item)
result.append(contentsOf: item.getAllChildModel())
}
return result
}
/// 获取需要展示所有子数据(包括子数据的子数据的子数据...递归操作,若父类 关闭,则不向下遍历)
/// - Returns: <#description#>
public func getAllShowChildModel() -> [HZJTreeViewModelProtocol] {
var result:[HZJTreeViewModelProtocol] = []
for item in self.childModels {
if item.isShowCurrent {
result.append(item)
}
if item._isOpen {
result.append(contentsOf: item.getAllShowChildModel())
}
}
return result
}
}
//MARK: - 私有属性
private extension HZJTreeViewModelProtocol {
/// 是否展示当前项
var _isShow:Bool {
set {
objc_setAssociatedObject(self, AssociationKey.from(#function), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
get{
guard let t = objc_getAssociatedObject(self, AssociationKey.from(#function)) as? Bool else {
return true//默认值
}
return t
}
}
/// 是否打开,以展示当前项的childModels
var _isOpen:Bool {
set {
objc_setAssociatedObject(self, AssociationKey.from(#function), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
get{
guard let t = objc_getAssociatedObject(self, AssociationKey.from(#function)) as? Bool else {
return false//默认值
}
return t
}
}
///等级
var _type:Int {
set {
objc_setAssociatedObject(self, AssociationKey.from(#function), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
get{
guard let t = objc_getAssociatedObject(self, AssociationKey.from(#function)) as? Int else {
return 1//默认值
}
return t
}
}
}
//MARK: - 私有的方法
private extension HZJTreeViewModelProtocol{
/// 递归设置子数据的type
func setAllChildModeType(_ currentType:Int){
for item in self.childModels {
let type = currentType + 1
item._type = type
item.setAllChildModeType(type)
}
}
}
使用时,需要数据遵循该协议
/// 数据模型,遵循HZJTreeViewModelProtocol就好
class HZJTreeModel: HZJTreeViewModelProtocol {
var fatherModel: HZJTreeViewModelProtocol?
var childModels: [HZJTreeViewModelProtocol] = []
/// 自定义的属性
var titleInfo: String = ""
/// 自定义便捷构造器
init(_ titleInfo:String) {
self.titleInfo = titleInfo
}
}
最后再cell中通过model中的type属性来区别显示
当然这里还有折叠/展示等逻辑,我就不再赘述,有兴趣的小伙伴可以看以我这个简单的代码,其实挺简单的😁
再来个运行想过图吧
来源:oschina
链接:https://my.oschina.net/wshzj/blog/4316710