CaamDauForm 4.3.0

CaamDauForm 4.3.0

lcd 维护。



  • by
  • liucaide

CI Status Version License Platform

Form (OC版本在这里

pod 'CaamDau'
pod 'CaamDau/Form'

目标:用一小段代码实现高耦合的 UI 排版解耦,增强排版随机、变更、扩展能力,增强 UI-Data 关联强度;解决TableView/CollectionView 混合排版 Delegate/DataSource 中 section row height didselect 等多关系的灾难

无论界面多复杂,都是一样的代码,使用这种方式即可轻松完成复杂的 UI 排版,编写可读性、扩展性、维护性强的代码

原理:这是一个 UI 排版模型,将 UI 排版逻辑事先转换为 Row 模型单元!

如何做到不需要再维护Delegate和DataSource协议的代码

  • 首先要明白 Delegate/DataSource 中的 section row height didselect 的多关系是有迹可循的,是可以模型化的,因此可以转化为单个模型单元,即可将多关系转化为单点关系。
  • 了解 CellProtocol 协议
  • 了解为 TableView/CollectionView 定制的 RowCell/RowCellClass
  • 了解 FormDelegateDataSource

如何构建一个单元格模型 Row

let row = RowCell<Cell_***>()

示例:

        do{// 倒计时 - 旧的协议
            let row = Row<Cell_MineCountDown>(data: model, frame: CGRect(h:100))
            self.forms[Section.countdown.rawValue].append(row)
        }
        
        do{// 倒计时 - 新的协议
            let row = RowCell<Cell_MineCountDown>(data: model, frame: CGRect(h:100))
            self.forms[Section.countdown.rawValue].append(row)
        }
        
        do{// 倒计时 点击回调didSelect 与内部事件回调 callBack
            let row = RowCell<Cell_MineCountDown>(data: model, frame: CGRect(h:100), callBack:{_ in}, didSelect:{})
            self.forms[Section.countdown.rawValue].append(row)
        }

如何应对混合排版

  • 当混合排版时,section row height didselect 等多关系简直是一场灾难
  • 而使用 Row 就如此简单

示例:

//MARK:--- 应对混合排版 ----------
extension VM_MineTableView{
    func makeForm() {
        for (i,item) in models.enumerated() {
            self.makeFormCountDown(item)
            // 除倒计时外 其余随机排版
            switch Int(arc4random() % 3) {
            case 0:...
            default:
                self.makeFormDetail(i)
            }
            
            do{//分割线
                let row = Row<Cell_MineLine>(data: .bgF0, frame: CGRect(h:10))
                self.forms[Section.countdown.rawValue].append(row)
            }
        }
    }
    func makeFormCountDown(_ model:VM_MineTableView.Model) {
        do{// 倒计时
            let row = Row<Cell_MineCountDown>(data: model, frame: CGRect(h:100))
            self.forms[Section.countdown.rawValue].append(row)
        }
        do{//分割线
            let row = Row<Cell_MineLine>(data: .bgF0, frame: CGRect(h:0.5))
            self.forms[Section.countdown.rawValue].append(row)
        }
    }
}

如何扩展实现自定义功能

  • Form *** DelegateDataSource 中已实现的 Delegate/DataSource 代码是通用代码,当无法满足需求时,可以继承 Form *** DelegateDataSource 来实现新的功能。
/// 继承 Form***DelegateDataSource 自行实现 左滑删除功能
class CustomListTableViewDelegateDataSource: FormTableViewDelegateDataSource {
    
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        // 特定状态 特定Cell 具备左滑删除
        guard let vm = vm as? VM_CustomList, vm.status == .t未提交, vm._forms[indexPath.section][indexPath.row].cellClass == Cell_CustomList.self else {
            return false
        }
        return true
    }
    func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
        return .delete
    }
    func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
        return "删除"
    }
    func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
        return false
    }
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        guard let vm = vm as? VM_CustomList, let model = vm._forms[indexPath.section][indexPath.row].dataSource as? VM_CustomList.List  else {
            return
        }
        vm.requestDelete(model)
    }
}

以前的混乱代码

  • 以往您的 TableView/CollectionView 可能是这样的;无论是开发、维护、修改都是灾难,section row height didselect 等必须相应维护,而且每个 TableView/CollectionView 都需要重复编写这些灾难性的代码。

示例:

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if section == * {return *} 
        else if section == * {return *} 
        else if section == * {return *} 
        // 自动忽略几十行代码
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        switch indexPath.section {
        case **:
            switch indexPath.row {
              case **:
               return cell
               // 自动忽略几十行代码
            }
            // 自动忽略几十行代码
        }
    }
    // 自动忽略几十行代码

现在有序的代码

  • 现在代码可以这样编写,无需维护 Delegate/DataSource 代理,将任务委托给 Form***DelegateDataSource(可扩展实现未完成的功能)。
    /// Cell数据源遵循 FormProtocol 协议
    var form:FormProtocol?
    /// tableView Delegate DataSource 代理类
    lazy var delegateData:FormTableViewDelegateDataSource? = {
        return FormTableViewDelegateDataSource(form)
    }()
    tableView.delegate = delegateData
    tableView.dataSource = delegateData
    delegateData?.makeReloadData(tableView)
  • 此时,一个单元格的全部信息都包含在 RowCell 模型中,无需理会 Delegate DataSource 中的代码。
    // 设置 活动分组 排版
    func makeActivityForm() {
        do{
            let row = RowCell<Cell_***>.init(data: "数据" config:"配置", frame: CGRect(h:45), callBack: { _ in
                /// Cell 内事件回调处理
            }) {
                /// Cell 点击事件处理
            }
            forms[Section.activity.rawValue] += [row]
        }
        do{
            let row = RowCell<Cell_***>.init(data: "数据", frame: CGRect(h:45))
            forms[Section.activity.rawValue] += [row]
        }
        reloadData?()
    }
    // 此处省略 各组 各种类型状态 下的排版顺序关系
  • 更多详细示例请运行 Demo 查看。

作者

liucaide, [email protected]

许可证

CaamDau 采用 MIT 许可证。更多信息和 LICENSE 文件。