开发笔记-Swift

让自定义 UITableViewCell 的使用更便捷

2019-08-23  本文已影响0人  周胖儿

在使用 UITableView 中,一个合乎 Apple 规范的 Cell 注册/使用流程需要至少两部分代码。
1.注册 Cell

tableView.register(MyCellClass.self, forCellReuseIdentifier: "CellIdentifier")
  1. 在 delegate 中完成 cell 的获取
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier") as! MyCellClass
    return cell
}

当项目中多处用到 UITableView 时,这样的松耦合的写法很容易犯错,在不慎把 reuseIdentifier 或 MyCellCalss 的类型写错时很难发现错误。为此,做一个如下的扩展也许很有意义:

// MARK: - 让单元格支持复用的协议。
public protocol UITableViewCellReusableSupport : class {
    /// 复用标识。
    static var reuseableIdentifier: String { get }
}
 
// MARK: - 提供 UITableViewCellReusableSupport 的默认实现。
public extension UITableViewCellReusableSupport where Self : UITableViewCell {
    /// 复用标识。
    static var reuseableIdentifier: String {
        return String(describing: self)
    }
}

// MARK: - 扩展 UITableView 的特性。
public extension UITableView {

    /// 注册一个可复用的单元格。
    ///
    /// - Parameter cellClass: 单元格类型。
    func register<T : UITableViewCell >(_ cellClass: T.Type) where T : UITableViewCellReusableSupport {
        self.register(cellClass, forCellReuseIdentifier: T.reuseableIdentifier)
    }
    
    /// 获取一个可复用的单元格。
    ///
    /// - Parameters:
    ///   - cellClass: 单元格类型。
    ///   - indexPath: 单元格位置。
    /// - Returns: 获取的单元格。
    func dequeueReusableCell<T : UITableViewCell>(_ cellClass: T.Type, for indexPath: IndexPath) -> T? where T : UITableViewCellReusableSupport {
        return self.dequeueReusableCell(withIdentifier: T.reuseableIdentifier, for: indexPath) as! T
    }
    
    /// 获取指定位置的单元格。
    ///
    /// - Parameters:
    ///   - cellClass: 单元格类型。
    ///   - indexPath: 单元格位置。
    /// - Returns: 获取的单元格。
    func cellForRow<T : UITableViewCell>(_ cellClass: T.Type, at indexPath: IndexPath ) -> T? where T : UITableViewCellReusableSupport {
        return self.cellForRow(at: indexPath) as? T
    }
}

搞定后,以后的代码可以这样写:

// 1. 自定义 UITableViewCell 时支持 UITableViewCellReusableSupport 协议
class MyTableViewCell: UITableViewCell, UITableViewCellReusableSupport {
}

// 2. 在 UITableView 中用如下方式注册 Cell
tableView.register(MyTableViewCell.self)

// 3. 在 delegate 中更精准的获取 Cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   // 获取的 cell 是 MyTableViewCell 类型,而不是 UITableViewCell 类型。
   let cell = tableView.dequeueReusableCell(MyTableViewCell.self, for: indexPath)
   return cell
}

// 4. 在使用 IndexPath 获取 Cell 时这样写
if let cell = tableView.cellForRow(MyTableViewCell.self, at: newIndexPath) {
   // 获取的 cell 是 MyTableViewCell 类型,而不是 UITableViewCell 类型。
}

最后,UICollectionView 也可以这样做。

上一篇 下一篇

猜你喜欢

热点阅读