TableCollectionManager 1.0.2

TableCollectionManager 1.0.2

Dima Mishchenko 维护。



  • Dmytro Mishchenko

TableCollectionManager

TableCollectionManager 是一个轻量级的泛型库,允许您使用声明式、类型安全的风格来构建表格视图和集合视图。

  • 类型安全的泛型单元格和模型

  • 函数式编程风格

  • 无需使用代理和数据源

  • 模型自动更新视图

目录

安装

  • 将以下内容添加到Podfile
pod 'TableCollectionManager'
  • 运行pod install
  • 添加到文件
import TableCollectionManager

使用

主要思想是你有一个管理器来管理表格/集合视图。并且这个管理器有存储,你可以更新其中的条目。然后发生魔法,视图会自动更新和重新加载。你还可以方便地以函数式风格处理操作。

TableView

表格快速上手

import TableCollectionManager

// create cell and implement TableConfigurable

class ExampleCell: UITableViewCell, TableConfigurable {
  
  func update(with model: String) {
    textLabel?.text = model
  }
}

class VC: UIViewController {
  
  // init manager
  let manager = TableManager()
  var tableView = UITableView(frame: .zero, style: .plain)
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    // set tableView to manager
    manager.tableView = tableView
    
    // create rows
    
    let firstRow = TableRow<ExampleCell>("First").didSelect { result in
      // result.model - cell model  
      // result.cell - cell 
			// result.indexPath - indexPath                       
      print("first")
    }
    
    let secondRow = TableRow<ExampleCell>("Second").didSelect { _ in                    
      print("second")
    }
    
    // add rows to storage
    manager.storage.append([firstRow, secondRow])
  }
}

TableCell

要使用带有TableManager的单元格,您必须实现TableConfigurable协议。

您需要实现update(with:)函数以提供模型类型。

假设您有一个Pet对象,您希望创建一个显示该项目数据的单元格。在这种情况下,单元格将如下所示。

struct Pet {
  
  let name: String
  let age: Int
}

class PetCell: UITableViewCell, TableConfigurable {
  
  func update(with model: Pet) {
    // fill cell with data 
    textLabel?.text = "\(model.name) is \(model.age) years old"
  }
}

您还可以提供单元格的heightestimatedHeight。默认情况下,它们等于UITableView.automaticDimension

class Cell: UITableViewCell, TableConfigurable {
  
  // custom height
  static var height: CGFloat { 
    44
  }
  
  // custom estimatedHeight
  static var estimatedHeight: CGFloat { 
    44
  }
  
  func update(with model: String) {
 
  }
}

您也无需注册单元格。TableManager会为您完成这一操作。

TableRow

TableRow 是单元格包装器。因此,您只需要为此行使用行和模型(viewModel)。

要创建 TableRow,请提供单元格类型和模型实例。

let pet = Pet(name: "Elon", age: 2)
let petRow = TableRow<PetCell>(pet)

您还可以订阅来自 UITableViewDelegate/UITableViewDataSource 的某些操作。例如,您想要此行的 didSelect。在这种情况下,只需调用 didSelect

petRow.didSelect { result in
  // do something
  // result.model - cell model  
  // result.cell - cell 	
  // result.indexPath - indexPath                       
}

TableRow 支持以下操作

  • didSelect

  • didDeselect

  • willSelect

  • willDeselect

  • willDisplay

  • didEndDisplaying

  • moveTo

  • shouldHighlight

  • editingStyle

  • leadingSwipeActions

  • trailingSwipeActions

  • canEdit

  • canMove

  • commitStyle

  • move

您还可以链式调用操作。

let row = TableRow<Cell>(model).didSelect { _ in
  print("selected")
}.willDisplay { _ in
  print("willDisplay")
}.canEdit { _ in
  return true
}

表头和页脚

表头和页脚几乎像单元格一样工作。唯一的区别是 estimatedHeight 是必需的。

class HeaderFooter: UITableViewHeaderFooterView, TableConfigurable {
  
  // required
  static var estimatedHeight: CGFloat {
    44
  }
  
  // optional (UITableView.automaticDimension by default)
  static var height: CGFloat { 
    44
  }
  
  func update(with model: String) {
    textLabel?.text = model
  }
}

TableHeaderFooter 是表头和页脚的包装器。要将它们添加到表格视图中,只需这样做。

let header = TableHeaderFooter<HeaderFooter>("Header")
// add header to section at index
manager.storage.setHeader(header, to: 0)

let footer = TableHeaderFooter<HeaderFooter>("Footer")
// add header to section at index
manager.storage.setFooter(footer, to: 1)

用户内容表格部分

用户内容表格部分UITableView 部分的包装。如果你在表格视图中有很多部分,你应该使用 用户内容表格部分。你可以为每个部分设置行、头和尾。

let rows = (1...10).map { TableRow<Cell>("\($0)") }
let header = TableHeaderFooter<HeaderFooter>("Header")
let footer = TableHeaderFooter<HeaderFooter>("Footer")

let section = TableSection(
  rows: rows,
  header: header,
  footer: footer
)

manager.storage.append(section)

用户内容存储

用户内容存储是一个存储所有部分和行的地方。每个TableManager都有一个存储空间。如果您向这个存储表传递数据,视图将自动更新。

manager.storage.append(sections)
manager.storage.delete(row)
manager.storage.reload(rows)
// and ect.

您还可以获取部分索引、行indexPath、索引处的部分或indexPath处的行。

let sectionIndex = manager.storage.index(for: section)
let rowIndexPath = manager.storage.indexPath(for: row)

let section = manager.storage.section(at: index)
let row = manager.storage.row(at: indexPath)

存储有performWithoutAnimation块。您在块内调用的每个更改都将无动画执行。

manager.storage.performWithoutAnimation {
  manager.storage.append(sections)
  manager.storage.reload(rows)
}

存储有performBatchUpdate块。在您希望在一个单个动画操作中对多个更改的情况下,可以使用此方法。

manager.storage.performBatchUpdate({
  manager.storage.append(sections)
  manager.storage.delete(row)
}, completion: { isFinished in
  // completion
})

所有存储功能

  • isEmpty

  • numberOfSections

  • numberOfAllRows

  • index(for section:<)

  • indexPath(for row:<)

  • section(at index:<)

  • row(at indexPath:<)

  • performWithoutAnimation(< block:)

  • performBatchUpdate(< block:, completion:)

  • reload()

  • reload(< row:)

  • reload(< rows:)

  • reload(< section:)

  • reload(< sections:)

  • append(< row:)

  • append(< rows:)

  • append(< row:, to sectionIndex:)

  • append(< rows:, to sectionIndex:)

  • append(< section:)

  • append(< sections:)

  • insert(< row:, at indexPath:)

  • insert(< section:, at index:)

  • delete(< row:)

  • delete(< rows:)

  • delete(< section:)

  • delete(< sections:)

  • deleteAllItems()

  • moveRowWithoutUpdate(from source:, to destination:)

  • moveRow(from source:, to destination:)

  • moveSection(from source:, to destination:)

TableManager

TableManager 是一个管理所有委托和数据源的对象。管理器包含 storagetableView。您可以更改这两个。

管理器还有一个 scrollHandler,它处理 UIScrollViewDelegate

manager.scrollHandler.didScroll {
  print("didScroll")
}.shouldScrollToTop {
  return true
}

CollectionView

用户内容集合快速入门

import TableCollectionManager

// create cell and implement CollectionConfigurable

class ExampleCell: UICollectionViewCell, CollectionConfigurable {
  
  func update(with model: String) {
    textLabel?.text = model
  }
}

class VC: UIViewController {
  
  // init manager
  let manager = CollectionManager()
	var collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    // set collectionView to manager
    manager.collectionView = collectionView
    
    // create rows
    
    let firstRow = CollectionRow<ExampleCell>("First").didSelect { result in
      // result.model - cell model  
      // result.cell - cell 
			// result.indexPath - indexPath                       
      print("first")
    }
    
    let secondRow = CollectionRow<ExampleCell>("Second").didSelect { _ in                    
      print("second")
    }
    
    // add rows to storage
    manager.storage.append([firstRow, secondRow])
  }
}

CollectionCell

要使用与TableManager一起使用的单元格,您必须实现CollectionConfigurable协议。

您需要实现update(with:)函数以提供模型类型。

假设您有一个Pet对象,您希望创建一个显示该项目数据的单元格。在这种情况下,单元格将如下所示。

struct Pet {
  
  let name: String
  let age: Int
}

class PetCell: UICollectionViewCell, CollectionConfigurable {
  
  func update(with model: Pet) {
    // fill cell with data 
  }
}

您还可以提供单元格的size。这是可选的,您也可以使用UICollectionViewLayout或使用CollectionManagerlayoutHandler来提供高度。

class Cell: UICollectionViewCell, CollectionConfigurable {
  
  // custom size
  static var size: CGSize? {
    CGSize(width: 44, height: 44)
  }
  
  func update(with model: String) {
 
  }
}

您也不需要注册单元格。CollectionManager会为您完成这项任务。

CollectionRow

CollectionRow 是对单元格的包装。因此,您只与此行的行和模型(viewModel)一起工作。

要创建 CollectionRow,请提供单元格类型和模型实例。

let pet = Pet(name: "Elon", age: 2)
let petRow = CollectionRow<PetCell>(pet)

您也可以订阅一些来自 UICollectionViewDelegate/UICollectionViewDataSource 的操作。例如,您想要对这个行的 didSelect。在这种情况下,只需调用 didSelect 即可。

petRow.didSelect { result in
  // do something
  // result.model - cell model  
  // result.cell - cell 	
  // result.indexPath - indexPath                       
}

CollectionRow 支持以下操作

  • didSelect

  • didDeselect

  • willDisplay

  • didEndDisplaying

  • moveTo

  • shouldHighlight

  • canMove

  • move

您还可以链式调用操作。

let row = CollectionRow<Cell>(model).didSelect { _ in
  print("selected")
}.willDisplay { _ in
  print("willDisplay")
}

CollectionHeaderFooter

页眉和页脚的工作方式几乎与单元格相同。大小处理方式与 CollectionRow 相同。

class HeaderFooter: UICollectionReusableView, CollectionConfigurable {
  
  // custom size
  static var size: CGSize? {
    CGSize(width: 44, height: 44)
  }
  
  func update(with model: String) {

  }
}

CollectionHeaderFooter 是页眉和页脚的包装器。您可以使用部分添加页眉/页脚。

let header = CollectionHeaderFooter<HeaderFooter>("Header")
let footer = CollectionHeaderFooter<HeaderFooter>("Footer")
let section = CollectionSection(
  rows: [],
  header: header,
  footer: footer
)

收藏部分

收藏部分是围绕UICollectioView部分的包装。如果你的表格视图中有多于一个部分,你应该使用收藏部分。你可以为每个部分设置行、标题和底部。

let rows = (1...10).map { CollectioRow<Cell>("\($0)") }
let header = CollectionHeaderFooter<HeaderFooter>("Header")
let footer = CollectionHeaderFooter<HeaderFooter>("Footer")

let section = CollectionSection(
  rows: rows,
  header: header,
  footer: footer
)

manager.storage.append(section)

CollectionStorage

CollectionStorage是所有部分和行存储的地方。每个CollectionManager都有一个存储空间。如果将数据传递到这个存储空间,视图将自动更新。

manager.storage.append(sections)
manager.storage.delete(row)
manager.storage.reload(rows)
// and ect.

您还可以获取部分索引、行indexPath、索引处的部分或indexPath处的行。

let sectionIndex = manager.storage.index(for: section)
let rowIndexPath = manager.storage.indexPath(for: row)

let section = manager.storage.section(at: index)
let row = manager.storage.row(at: indexPath)

存储有performWithoutAnimation块。您在块内调用的每个更改都将无动画执行。

manager.storage.performWithoutAnimation {
  manager.storage.append(sections)
  manager.storage.reload(rows)
}

存储有performBatchUpdate块。在您希望在一个单个动画操作中对多个更改的情况下,可以使用此方法。

manager.storage.performBatchUpdate({
  manager.storage.append(sections)
  manager.storage.delete(row)
}, completion: { isFinished in
  // completion
})

所有存储功能与TableStorage相同。

集合管理器

集合管理器是一个管理所有代理和数据源的物体。管理器包含存储集合视图。您可以更改它们两个。

管理器还有一个 scrollHandler,它处理 UIScrollViewDelegate

manager.scrollHandler.didScroll {
  print("didScroll")
}.shouldScrollToTop {
  return true
}

管理器还有布局处理,可以处理UICollectionViewDelegateFlowLayoutcollectionView(_ :transitionLayoutForOldLayout:newLayout:)代理方法。

例如,您可以提供项的大小。

manager.layoutHandler.sizeForItem { indexPath in
  return CGSize(width: 44, height: 44)
}.sizeForHeader { sectionIndex in
  return CGSize(width: 44, height: 44)
}

许可证

TableCollectionManager 采用 MIT 许可证。有关更多信息,请参阅 LICENSE 文件。