Classes

The following classes are available globally.

  • Default DiffableDataSource that provides the logic to section provides updates to xDiffCollection that is used as a Backstorage those updates are used by DiffableTableViewDataSource to tell UITableView what to reload,insert or delete

    Declaration

    Swift

    public class DiffableDataSource : NSObject
  • Class adapter to provide section filter. Based on the filter function DiffableDataSource decides what goes into a particular section.

    • Generic type T stands for type of a model.
    • Generic type S stands for the unique ID of a Section

    Usage Example

    • Assuming we have the next model:
    enum TextModelMockType: String {
        case type1
        case type2
        case type3
    }
    
    /// Type represent unique item
    /// Text is something that is dynamic and can be changed
    struct TextModelMock: Hashable {
        let text: String
        let type: TextModelMockType
    
        func hash(into hasher: inout Hasher) {
            hasher.combine(type)
        }
    
        static func == (lhs: Self, rhs: Self) -> Bool {
            lhs.text == rhs.text
        }
    }
    
    
    See more

    Declaration

    Swift

    public final class DiffableDataSourceFilter<T, S> where T : Hashable, S : Hashable
  • Class - container that allows to append different type of filters Used during initialization of DiffableDataSource

    See more

    Declaration

    Swift

    public class DiffableDataSourceFilterProvider
  • Generic class that represents suggested updates to the DiffableDataSource

    See more

    Declaration

    Swift

    open class GenericSectionUpdate<RowModel, SectionID> where
        RowModel: Hashable,
        SectionID: Hashable
  • The core of EZSource for UITableView. Provides declarative API to work with UITableView All you need is to initialize the source, create rows, add them to section updates and call update function The rest is handled by EZSource, next time you have to update the UITableView, EZSource will find take care about inserting, deleting or reloading rows using animation provided in the section updates

    Usage Example

    • Define a Cell Model
    struct StringCellModel:  Hashable  {
      let uniqueID: String
      let text: String
    
      // Defines uniqueness of the model
      func hash(into hasher: inout Hasher) {
          hasher.combine(uniqueID)
      }
    
      // Defines dynamic context of the model
      static func == (lhs: Self, rhs: Self) -> Bool {
          lhs.text == rhs.text
      }
    }
    
    • Define a Cell
    final class StringCell: UITableViewCell, ReusableCell, Configurable {
      typealias Model = StringCellModel
    
      func configure(with model: StringCellModel) {
          textLabel?.text = "ID: \(model.uniqueID): \(model.text)"
          selectionStyle = .none
      }
    }
    
    • Create Data Source
    let config = DiffableTableViewDataSource.Config(tableView: tableView,
                                                    cellTypes: [StringCell.self],
                                                    headerFooters: [TestReusableView.self])
    source = DiffableTableViewDataSource(config: config)
    
    let model = StringCellModel(uniqueID: ID, text: title)
    let row = TableViewRow<StringCell>(model: model,
                                     onTap: { debugPrint("tapped with \($0)")})
    // add rows if need
    row.addRowLeadingActions(leadingActions)
    row.addRowTrailingActions(trailingActions)
    
    • Add the row to the cell
    let updates = TableViewDiffableSection(id: "SectionID here")
    updates.addRows([row])
    
    • Create a ReusableView
    final class TestReusableView: ReusableView, Configurable {
    
       let label: UILabel
       override init(reuseIdentifier: String?) {
           // Init and Configure UILabel
    
           super.init(reuseIdentifier: reuseIdentifier)
       }
    
       required init?(coder aDecoder: NSCoder) {
           super.init(coder: aDecoder)
       }
    
       func configure(with txt: String) {
           label.text = txt
       }
    }
    
    
    • Create a header
    let text = "My custom section"
    let footer = ImmutableHeaderFooterProvider<TestReusableView>(model: text)
    
    let updates = TableViewDiffableSection(id: "SectionID here")
    updates.addHeader(header)
    
    • Call updates on the source
    source.update(sections: [updates])
    
    See more

    Declaration

    Swift

    public final class DiffableTableViewDataSource : DiffableDataSource
    extension DiffableTableViewDataSource: UITableViewDataSource
    extension DiffableTableViewDataSource: UITableViewDelegate
  • Represents changes proposed to a section Example

    • Define a Cell Model
    struct StringCellModel:  Hashable  {
       let uniqueID: String
       let text: String
    
       // Defines uniqueness of the model
       func hash(into hasher: inout Hasher) {
           hasher.combine(uniqueID)
       }
    
       // Defines dynamic context of the model
       static func == (lhs: Self, rhs: Self) -> Bool {
           lhs.text == rhs.text
       }
    }
    
    • Define a Cell
    final class StringCell: UITableViewCell, ReusableCell, Configurable {
       typealias Model = StringCellModel
    
       func configure(with model: StringCellModel) {
           textLabel?.text = "ID: \(model.uniqueID): \(model.text)"
           selectionStyle = .none
       }
    }
    
    let model = StringCellModel(uniqueID: ID, text: title)
    let row = TableViewRow<StringCell>(model: model,
                                      onTap: { debugPrint("tapped with \($0)")})
    // add rows if need
    row.addRowLeadingActions(leadingActions)
    row.addRowTrailingActions(trailingActions)
    
    • Add the row to the cell
    let updates = TableViewDiffableSection(id: "SectionID here")
    updates.addRows([row])
    
    • Create a ReusableView
    final class TestReusableView: ReusableView, Configurable {
    
        let label: UILabel
        override init(reuseIdentifier: String?) {
            // Init and Configure UILabel
    
            super.init(reuseIdentifier: reuseIdentifier)
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        func configure(with txt: String) {
            label.text = txt
        }
    }
    
    
    • Create a header
    let text = "My custom section"
    let footer = ImmutableHeaderFooterProvider<TestReusableView>(model: text)
    
    • Attach the header to a TableViewDiffableSection
    let updates = TableViewDiffableSection(id: "SectionID here")
    updates.addHeader(header)
    
    See more

    Declaration

    Swift

    public final class TableViewDiffableSection : GenericSectionUpdate<AnyHashable, String>
  • The absctract class to provide a section header or footer view

    Warning:

    Using this class as is will cause a CRASH

    See more

    Declaration

    Swift

    public class HeaderFooterProvider<View>: SectionHeaderFooterProvider
    where View: Configurable & ReusableView
  • Default class that is responsible to dequeue a reusable view and configure it

    Note

    if the height is nil then you should make UIView as a self-sized view

    Usage Example

    • Create a ReusableView
    final class TestReusableView: ReusableView, Configurable {
    
        let label: UILabel
        override init(reuseIdentifier: String?) {
            // Init and Configure UILabel
    
            super.init(reuseIdentifier: reuseIdentifier)
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        func configure(with txt: String) {
            label.text = txt
        }
    }
    
    
    • Create a header
    let text = "My custom section"
    let header = ImmutableHeaderFooterProvider<TestReusableView>(model: text)
    
    let updates = TableViewDiffableSection(id: "SectionID here")
    updates.addHeader(header)
    
    See more

    Declaration

    Swift

    public class ImmutableHeaderFooterProvider<View>: HeaderFooterProvider<View>
    where View: Configurable & ReusableView
  • Default class that is responsible to dequeue a reusable view and configure it In addition provides an update method to change the model.

    Note

    if the height is nil then you should make UIView as a self-sized view

    Usage Example

    • Create a ReusableView
       final class TestReusableView: ReusableView, Configurable {
    
           let label: UILabel
           override init(reuseIdentifier: String?) {
               // Init and Configure UILabel
    
               super.init(reuseIdentifier: reuseIdentifier)
           }
    
           required init?(coder aDecoder: NSCoder) {
               super.init(coder: aDecoder)
           }
    
           func configure(with txt: String) {
               label.text = txt
           }
       }
    
    
    • Create a header
       let text = "My custom section"
       // Store the header so you can reference to it later
       let header = MutableHeaderFooterProvider<TestReusableView>(model: text)
    
       let updates = TableViewDiffableSection(id: "SectionID here")
       updates.addHeader(header)
       // call datasource update
       header.update(model: "New text here")
    
    See more

    Declaration

    Swift

    public class MutableHeaderFooterProvider<View>: HeaderFooterProvider<View>
    where View: Configurable & ReusableView
  • Higher-API class for UIContextualAction

    **Example Usage**
    - Create Action
    
    ````
    var rowAction: RowAction {
        RowAction { [weak self] in
            guard let `self` = self else { return }
            let alertController = self.alertControllerExample
            let act = self.dismissAction(for: alertController)
            alertController.addAction(act)
            self.present(alertController, animated: true, completion: nil)
        }
    }
    ````
    - set up title and color
    
    ````
    var leadingActions: [RowAction] {
        let action = rowAction
        action.backgroundColor = .green
        action.title = "Done"
        return [action]
    }
    ````
    - add to a row
    
    ````
    let model = StringCellModel(uniqueID: ID, text: title)
    let row = TableViewRow<StringCell>(model: model,
                                       onTap: { debugPrint("tapped with \($0)")})
    row.addRowLeadingActions(leadingActions)
    
    ````
    
    See more

    Declaration

    Swift

    public class RowAction
  • The concept of a generic TableViewCell:

    • it knows about model it operates with
    • contains tap closure that is called when a cell is tapped
    • responsible for dequeueing a cell
    • provides methods to add leading / trailing actions

    Example

    • Define a Cell Model
      struct StringCellModel:  Hashable  {
          let uniqueID: String
          let text: String
    
          // Defines uniqueness of the model
          func hash(into hasher: inout Hasher) {
              hasher.combine(uniqueID)
          }
    
          // Defines dynamic context of the model
          static func == (lhs: Self, rhs: Self) -> Bool {
              lhs.text == rhs.text
          }
      }
    
    • Define a Cell
      final class StringCell: UITableViewCell, ReusableCell, Configurable {
          typealias Model = StringCellModel
          let checkmarkView = UIView()
    
          func configure(with model: StringCellModel) {
              textLabel?.text = "ID: \(model.uniqueID): \(model.text)"
              selectionStyle = .none
          }
    
          override var isSelected: Bool {
              didSet {
                  debugPrint(isSelected)
              }
          }
    
          override func prepareForReuse() {
              accessoryType = .none
          }
    
          override func setSelected(_ selected: Bool, animated: Bool) {
    
              if selected {
                 accessoryType = .checkmark
              } else {
                 accessoryType = .none
              }
              super.setSelected(selected, animated: animated)
    
          }
      }
    
    • create a TableViewRow
      let model = StringCellModel(uniqueID: ID, text: title)
      let row = TableViewRow<StringCell>(model: model,
                                         onTap: { debugPrint("tapped with \($0)")})
      // add rows if need
      row.addRowLeadingActions(leadingActions)
      row.addRowTrailingActions(trailingActions)
    
    See more

    Declaration

    Swift

    public class TableViewRow<Cell> : CellProvider where Cell : UITableViewCell, Cell : Configurable, Cell : Reusable
    extension TableViewRow: Hashable, Equatable where Cell.Model: Hashable & Equatable