Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] Complete Public API Documentation #90

Merged
merged 1 commit into from
Jan 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions Sources/AccessibilityFormats.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,53 +16,66 @@

import Foundation

/// Wrapper `struct` for the `accessibilityIdentifier` format that should be applied to the cells of a `UITableView` or a `UICollectionView`
// Note: The accessibility types below are not documented as they are not intended to be part
// of the `ReactiveLists` project in the long term. See https://github.com/plangrid/ReactiveLists/issues/77

/// :nodoc:
public struct CellAccessibilityFormat: ExpressibleByStringLiteral {
private let _format: String

/// :nodoc:
public init(_ format: String) {
self._format = format
}

/// :nodoc:
public init(stringLiteral value: StringLiteralType) {
self._format = value
}

/// :nodoc:
public init(extendedGraphemeClusterLiteral value: String) {
self._format = value
}

/// :nodoc:
public init(unicodeScalarLiteral value: String) {
self._format = value
}

/// :nodoc:
public func accessibilityIdentifierForIndexPath(_ indexPath: IndexPath) -> String {
return self._format.replacingOccurrences(of: "%{section}", with: String(indexPath.section))
.replacingOccurrences(of: "%{item}", with: String(indexPath.item))
.replacingOccurrences(of: "%{row}", with: String(indexPath.row))
}
}

/// Wrapper `struct` for the `accessibilityIdentifier` format that should be applied to the headers and footers of a `UITableView` or a `UICollectionView`
/// :nodoc:
public struct SupplementaryAccessibilityFormat: ExpressibleByStringLiteral {
private let _format: String

/// :nodoc:
public init(_ format: String) {
self._format = format
}

/// :nodoc:
public init(stringLiteral value: StringLiteralType) {
self._format = value
}

/// :nodoc:
public init(extendedGraphemeClusterLiteral value: String) {
self._format = value
}

/// :nodoc:
public init(unicodeScalarLiteral value: String) {
self._format = value
}

/// :nodoc:
public func accessibilityIdentifierForSection(_ section: Int) -> String {
return self._format.replacingOccurrences(of: "%{section}", with: String(section))
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/CollectionViewDriver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ extension CollectionViewDriver: UICollectionViewDataSource {

/// :nodoc:
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.collectionViewModel?[section]?.cellViewModels?.count ?? 0
return self.collectionViewModel?[section]?.cellViewModels.count ?? 0
}

/// :nodoc:
Expand Down
33 changes: 18 additions & 15 deletions Sources/CollectionViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public protocol CollectionViewCellViewModel {

/// Asks the cell model to update the `UICollectionViewCell` with the content
/// in the cell model and return the updated cell.
/// - Parameter cell: the cell which contents need to be updated.
/// - Parameter cell: the cell which's content need to be updated.
func applyViewModelToCell(_ cell: UICollectionViewCell)
}

Expand All @@ -50,9 +50,14 @@ public extension CollectionViewCellViewModel {

/// View model for supplementary views in collection views.
public protocol CollectionViewSupplementaryViewModel {
/// Metadata for this supplementary view.
var viewInfo: SupplementaryViewInfo? { get }
/// Height of this supplementary view.
var height: CGFloat? { get }

/// Asks the supplementary view model to update the `UICollectionReusableView` with the content
/// in the model and return the updated view.
/// - Parameter view: the view which's content need to be update.
func applyViewModelToView(_ view: UICollectionReusableView)
}

Expand Down Expand Up @@ -89,9 +94,8 @@ public struct CollectionViewModel {
///
/// - Parameter indexPath: the index path for the cell that is being retrieved
public subscript(indexPath: IndexPath) -> CollectionViewCellViewModel? {
guard let section = self[indexPath.section],
let cellViewModels = section.cellViewModels, cellViewModels.count > indexPath.item else { return nil }
return cellViewModels[indexPath.item]
guard let section = self[indexPath.section], section.cellViewModels.count > indexPath.item else { return nil }
return section.cellViewModels[indexPath.item]
}

/// Provides a description of the collection view content in terms of diffing keys. These diffing keys
Expand All @@ -105,12 +109,12 @@ public struct CollectionViewModel {
}

// Ensure we have a diffing key for each cell in this section
let cellDiffingKeys: [DiffingKey] = section.cellViewModels?.map { cell in
let cellDiffingKeys: [DiffingKey] = section.cellViewModels.map { cell in
guard let cell = cell as? DiffableViewModel else {
fatalError("When diffing is enabled you need to provide cells which are DiffableViews.")
}
return "\(type(of: cell))_\(cell.diffingKey)"
} ?? []
}

return (sectionDiffingKey, cellDiffingKeys)
}
Expand All @@ -122,8 +126,7 @@ public struct CollectionViewModel {
public struct CollectionViewSectionViewModel {

/// Cells to be shown in this section.
let cellViewModels: [CollectionViewCellViewModel]?

let cellViewModels: [CollectionViewCellViewModel]
/// View model for the header of this section.
let headerViewModel: CollectionViewSupplementaryViewModel?

Expand All @@ -143,12 +146,12 @@ public struct CollectionViewSectionViewModel {
/// Initializes a collection view section view model.
///
/// - Parameters:
/// - cellViewModels: the cells in this section, or `nil`.
/// - headerViewModel: the header view model, or `nil`.
/// - footerViewModel: the footer view model, or `nil`.
/// - cellViewModels: the cells in this section.
/// - headerViewModel: the header view model (defaults to `nil`).
/// - footerViewModel: the footer view model (defaults to `nil`).
/// - diffingKey: the diffing key, required for automated diffing.
public init(
cellViewModels: [CollectionViewCellViewModel]?,
cellViewModels: [CollectionViewCellViewModel],
headerViewModel: CollectionViewSupplementaryViewModel? = nil,
footerViewModel: CollectionViewSupplementaryViewModel? = nil,
diffingKey: String? = nil
Expand Down Expand Up @@ -177,7 +180,7 @@ extension CollectionViewSectionViewModel {

/// :nodoc:
public init(
cellViewModels: [CollectionViewCellViewModel]?,
cellViewModels: [CollectionViewCellViewModel],
headerHeight: CGFloat? = nil,
footerViewModel: CollectionViewSupplementaryViewModel? = nil,
diffingKey: String? = nil
Expand All @@ -192,7 +195,7 @@ extension CollectionViewSectionViewModel {

/// :nodoc:
public init(
cellViewModels: [CollectionViewCellViewModel]?,
cellViewModels: [CollectionViewCellViewModel],
headerViewModel: CollectionViewSupplementaryViewModel? = nil,
footerHeight: CGFloat? = nil,
diffingKey: String? = nil
Expand All @@ -207,7 +210,7 @@ extension CollectionViewSectionViewModel {

/// :nodoc:
public init(
cellViewModels: [CollectionViewCellViewModel]?,
cellViewModels: [CollectionViewCellViewModel],
headerHeight: CGFloat? = nil,
footerHeight: CGFloat? = nil,
diffingKey: String? = nil
Expand Down
10 changes: 9 additions & 1 deletion Sources/Diffing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,16 @@

import Foundation

/// A view that can participate in an automatic diffing algorithm.
/// A view model that can participate in an automatic diffing algorithm.
public protocol DiffableViewModel {
/// The key used by the diffing algorithm to uniquely identify an element.
/// If you are using automatic diffing on a `*Driver` (which is enabled by default)
/// you are required to provide a key that uniquely identifies each element.
///
/// Typically you want to base this diffing key on data that is stored in the model.
/// For example:
///
/// public var diffingKey = { group.identifier }
var diffingKey: DiffingKey { get }
}

Expand Down
24 changes: 17 additions & 7 deletions Sources/SupplementaryViewInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,31 @@ import UIKit

/// Metadata thats required for setting up a supplementary view.
public struct SupplementaryViewInfo {

/// Stores how the view was registered (as a class or via a nib file)
public let registrationMethod: ViewRegistrationMethod

/// The reuse identifier for this supplementary view
public let reuseIdentifier: String

/// The kind of supplementary view (e.g. `header` or `footer`)
public let kind: SupplementaryViewKind

/// `TableViewDataSource` and `CollectionViewDataSource` will automatically apply
/// an `accessibilityIdentifier` to the supplementary view based on this format.
public let accessibilityFormat: SupplementaryAccessibilityFormat

public init(registrationMethod: ViewRegistrationMethod,
reuseIdentifier: String,
kind: SupplementaryViewKind,
accessibilityFormat: SupplementaryAccessibilityFormat) {
/// Initializes the metadata for a supplementary view.
///
/// - Parameters:
/// - registrationMethod: describes how the view was registered (as a class or via a nib file)
/// - reuseIdentifier: reuse identifier for this supplementary view
/// - kind: kind of supplementary view (e.g. `header` or `footer`)
/// - accessibilityFormat: a format string that generates an accessibility identifier for
/// the view that will be mapped to this view model.
public init(
registrationMethod: ViewRegistrationMethod,
reuseIdentifier: String,
kind: SupplementaryViewKind,
accessibilityFormat: SupplementaryAccessibilityFormat
) {
self.registrationMethod = registrationMethod
self.reuseIdentifier = reuseIdentifier
self.kind = kind
Expand Down
6 changes: 3 additions & 3 deletions Sources/TableViewDriver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ open class TableViewDriver: NSObject {
/// were moved/inserted/deleted.
///
/// For details, see the documentation for `TableViewDriver.tableViewModel`.
private let automaticDiffingEnabled: Bool
private let _automaticDiffingEnabled: Bool

private let _shouldDeselectUponSelection: Bool
private var _tableViewDiffer: TableViewDiffCalculator<DiffingKey, DiffingKey>?
Expand All @@ -88,7 +88,7 @@ open class TableViewDriver: NSObject {
) {
self.tableViewModel = tableViewModel
self.tableView = tableView
self.automaticDiffingEnabled = automaticDiffingEnabled
self._automaticDiffingEnabled = automaticDiffingEnabled
self._shouldDeselectUponSelection = shouldDeselectUponSelection
super.init()
tableView.dataSource = self
Expand Down Expand Up @@ -164,7 +164,7 @@ open class TableViewDriver: NSObject {

self.tableView.registerViews(for: newModel)

if self.automaticDiffingEnabled {
if self._automaticDiffingEnabled {
if !self._didReceiveFirstNonNilValue {
// For the first non-nil value, we want to reload data, to avoid a weird
// animation where we animate in the initial state
Expand Down
22 changes: 20 additions & 2 deletions Sources/TableViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ public struct TableViewSectionViewModel {
public let cellViewModels: [TableViewCellViewModel]

/// View model for the header of this section.

public let headerViewModel: TableViewSectionHeaderFooterViewModel?

/// View model for the footer of this section.
Expand All @@ -131,6 +130,14 @@ public struct TableViewSectionViewModel {
return self.cellViewModels.isEmpty
}

/// Initializes a `TableViewSectionViewModel`.
///
/// - Parameters:
/// - cellViewModels: the cell view models contained in this section.
/// - headerViewModel: a header view model for this section (defaults to `nil`).
/// - footerViewModel: a footer view model for this section (defaults to `nil`).
/// - collapsed: whether or not this section is collapsed (defaults to `false`).
/// - diffingKey: the diffing key, or `nil`. Required for automated diffing.
public init(
cellViewModels: [TableViewCellViewModel],
headerViewModel: TableViewSectionHeaderFooterViewModel? = nil,
Expand All @@ -145,14 +152,25 @@ public struct TableViewSectionViewModel {
self.diffingKey = diffingKey
}

/// Initializes a `TableViewSectionViewModel`.
///
/// - Parameters:
/// - headerTitle: title for the header, or `nil`. Setting a title will cause a default header
/// to be added to this section.
/// - headerHeight: the height of the default header, if one exists.
/// - cellViewModels: the cell view models contained in this section.
/// - footerTitle: title for the footer, or `nil`. Setting a title will cause a default footer
/// to be added to this section.
/// - footerHeight: the height of the default footer, if one exists.
/// - diffingKey: the diffing key, or `nil`. Required for automated diffing.
public init(
headerTitle: String?,
headerHeight: CGFloat?,
cellViewModels: [TableViewCellViewModel],
footerTitle: String? = nil,
footerHeight: CGFloat? = 0,
diffingKey: String? = nil
) {
) {
self.cellViewModels = cellViewModels
self.headerViewModel = PlainHeaderFooterViewModel(title: headerTitle, height: headerHeight)
self.footerViewModel = PlainHeaderFooterViewModel(title: footerTitle, height: footerHeight)
Expand Down
7 changes: 7 additions & 0 deletions Sources/Typealiases.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,17 @@

import Foundation

/// :nodoc:
public typealias CommitEditingStyleClosure = (UITableViewCellEditingStyle) -> Void
/// :nodoc:
public typealias DidSelectClosure = () -> Void
/// :nodoc:
public typealias DidDeleteClosure = () -> Void
/// :nodoc:
public typealias DidDeselectClosure = () -> Void
/// :nodoc:
public typealias WillBeginEditingClosure = () -> Void
/// :nodoc:
public typealias DidEndEditingClosure = () -> Void
/// :nodoc:
public typealias AccessoryButtonTappedClosure = () -> Void
6 changes: 3 additions & 3 deletions Tests/CollectionView/CollectionViewDriverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ final class CollectionViewDriverTests: XCTestCase {
self._collectionView = TestCollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewLayout())
self._collectionViewModel = CollectionViewModel(sectionModels: [
CollectionViewSectionViewModel(
cellViewModels: nil,
cellViewModels: [],
headerViewModel: TestCollectionViewSupplementaryViewModel(height: 10, viewKind: .header, sectionLabel: "A"),
footerViewModel: TestCollectionViewSupplementaryViewModel(height: 11, viewKind: .footer, sectionLabel: "A")),
CollectionViewSectionViewModel(
Expand All @@ -44,7 +44,7 @@ final class CollectionViewDriverTests: XCTestCase {
headerViewModel: TestCollectionViewSupplementaryViewModel(label: "header_C", height: 30),
footerViewModel: nil),
CollectionViewSectionViewModel(
cellViewModels: nil,
cellViewModels: [],
headerViewModel: TestCollectionViewSupplementaryViewModel(height: nil, viewKind: .header, sectionLabel: "D"),
footerViewModel: TestCollectionViewSupplementaryViewModel(height: nil, viewKind: .footer, sectionLabel: "D")),
])
Expand Down Expand Up @@ -209,7 +209,7 @@ final class CollectionViewDriverTests: XCTestCase {

self._collectionViewDataSource.collectionViewModel = CollectionViewModel(sectionModels: [
CollectionViewSectionViewModel(
cellViewModels: nil,
cellViewModels: [],
headerViewModel: TestCollectionViewSupplementaryViewModel(height: 10, viewKind: .header, sectionLabel: "X"),
footerViewModel: TestCollectionViewSupplementaryViewModel(height: 11, viewKind: .footer, sectionLabel: "X")),
CollectionViewSectionViewModel(
Expand Down
Loading