Skip to content

Commit

Permalink
Merge pull request #93 from mansbernhardt/section-reusable
Browse files Browse the repository at this point in the history
Adds new `HeaderFooterReusable` protocol to allow providing separate `Reus…
  • Loading branch information
mansbernhardt authored Mar 12, 2019
2 parents 5242f3f + 502b639 commit c31c4e2
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 3 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 1.7.0

- Adds new `HeaderFooterReusable` protocol to allow providing separate `Reusable` types for rendering a section's header and footer.
- Adds letter spacing and line height to `TextStyle`.
- Adds target offset to `willEndDragging` signal of `ScrollViewDelegate`.
- Adds will display cell signal to `CollectionViewDelegate`.

## 1.6.3
- Performace. Added custom `count` implementation for `TableSection` to improve performance of e.g. `Table.isValidIndex` that might be called a lot for large tables.

Expand Down
22 changes: 22 additions & 0 deletions Documentation/Tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,28 @@ If you are ok with losing type information you can also consider using the `Mixe
var mixedTable = Table<(), MixedReusable>(rows: [.init(1), .init("A"), .init("B"), .init(2)])
```

## HeaderFooterReusable

If you conform your `Table`'s `Section` type to `Reusable` a table's section will be rendered by the view provided by `makeAndConfigure()`. However if you like to provide both a header and a footer view from your section model data, you can conform your `Section` type to `HeaderFooterReusable` and provide separate header and footer types for rendering:

```swift
struct MySection { ... }

extension MySection: HeaderFooterReusable {
var header: MyHeaderType { ... }
var footer: MyFooterType { ... }
}
```

As it is common with header and footer that are just strings, Form includes the `HeaderFooter` type for your convenience:

```swift
struct HeaderFooter: HeaderFooterReusable, Hashable {
var header: String
var footer: String
}
```

## TableKit

Once you have your data in a `Table` and your `Row` and `Section` types conforming to `Reusable`, you can construct a `TableKit` that will provide a `UITableView` set up with a proper data source and delegate:
Expand Down
4 changes: 4 additions & 0 deletions Examples/Demo/Example/Contents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ extension UIViewController {
bag += section.appendRow(title: "TableKit and Nested Either Reusable").append(.chevron).onValueDisposePrevious {
present { $0.presentTableUsingKitAndNestedEitherReusable(style: style) }
}

bag += section.appendRow(title: "TableKit and HeaderFooterReusable").append(.chevron).onValueDisposePrevious {
present { $0.presentTableUsingKitAndHeaderFooterReusable(style: style) }
}
}

bag += self.install(form)
Expand Down
2 changes: 1 addition & 1 deletion Examples/Demo/Example/CustomStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ extension TextStyle {
static let regularButton = TextStyle(font: .regularButton, color: .mintGreenDark, alignment: .center)
static let disabledButton = TextStyle(font: .regularButton, color: .textGray, alignment: .center)
static let whiteButton = TextStyle(font: .regularButton, color: .white, alignment: .center)
static let headerText = TextStyle(font: .headerText, color: .textGray).restyled { $0.kerning = 0.8 }.uppercased
static let headerText = TextStyle(font: .headerText, color: .textGray).restyled { $0.letterSpacing = 0.8 }.uppercased
static let footer = smallText.centerAligned.multilined()
static let headerBlack = headerText.colored(.black).multilined()
static let header = headerText.multilined()
Expand Down
18 changes: 18 additions & 0 deletions Examples/Demo/Example/Tables.swift
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,21 @@ extension UIViewController {

return bag
}

func presentTableUsingKitAndHeaderFooterReusable(style: DynamicTableViewFormStyle) -> Disposable {
displayableTitle = "TableKit and HeaderFooterReusable"
let bag = DisposeBag()

let tableKit = TableKit(table: sectionTable, style: style, bag: bag)
bag += self.install(tableKit.view)

bag += self.navigationItem.addItem(UIBarButtonItem(title: "Swap"), position: .right).onValue {
swap(&sectionTable, &swapSectionTable)
tableKit.set(sectionTable)
}

return bag
}
}

private var table = Table(sections: [("Header 1", 0..<5), ("Header 2", 5..<10)])
Expand All @@ -220,3 +235,6 @@ extension Double: Reusable {
})
}
}

private var sectionTable = Table(sections: [(HeaderFooter(header: "Header 1", footer: "Footer 1"), 0..<5), (HeaderFooter(header: "Header 2", footer: "Footer 2"), 5..<10)])
private var swapSectionTable = Table(sections: [(HeaderFooter(header: "Header 1", footer: "Footer 1"), 0..<2), (HeaderFooter(header: "Header 1b", footer: "Footer 1b"), 3..<7), (HeaderFooter(header: "Header 2", footer: "Footer 2"), 7..<10)])
2 changes: 1 addition & 1 deletion Form/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.6.3</string>
<string>1.7.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
13 changes: 13 additions & 0 deletions Form/Reusable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,16 @@ extension Either: Reusable where Left: Reusable, Right: Reusable, Left.ReuseType
}
}
}

/// Conforming types specifies what `Reusable` conforming types to use for a section's header and footer.
/// If you need both a header and footer you typically conforms your `Table`'s `Section` type to this protocol.
public protocol HeaderFooterReusable {
associatedtype Header: Reusable
associatedtype Footer: Reusable

/// The value use to render a section's header
var header: Header { get }

/// The value use to render a section's footer
var footer: Footer { get }
}
16 changes: 16 additions & 0 deletions Form/TableKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,22 @@ public extension TableKit where Row: Reusable, Row.ReuseType: ViewRepresentable,
}
}

public extension TableKit where Row: Reusable, Row.ReuseType: ViewRepresentable, Section: HeaderFooterReusable, Section.Header.ReuseType: ViewRepresentable, Section.Footer.ReuseType: ViewRepresentable {
/// Creates a new instance
/// - Parameters:
/// - table: The initial table. Defaults to an empty table.
/// - bag: A bag used to add table kit activities.
convenience init(table: Table = Table(), style: DynamicTableViewFormStyle = .default, view: UITableView? = nil, bag: DisposeBag) {
self.init(table: table, style: style, view: view, bag: bag, headerForSection: { table, section in
table.dequeueHeaderFooterView(forItem: section.header, style: style.header, formStyle: style.form, reuseIdentifier: "header")
}, footerForSection: { table, section in
table.dequeueHeaderFooterView(forItem: section.footer, style: style.footer, formStyle: style.form, reuseIdentifier: "footer")
}, cellForRow: { table, row in
table.dequeueCell(forItem: row, style: style)
})
}
}

extension TableKit: SignalProvider {
public var providedSignal: ReadWriteSignal<Table> {
return ReadSignal(capturing: self.table, callbacker: callbacker).writable(signalOnSet: true) { self.table = $0 }
Expand Down
10 changes: 10 additions & 0 deletions Form/UITableViewHeaderFooterView+Utilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,16 @@ extension String: Reusable {
}
}

public struct HeaderFooter: HeaderFooterReusable, Hashable {
public var header: String
public var footer: String

public init(header: String, footer: String) {
self.header = header
self.footer = footer
}
}

public struct DateHeader: Equatable {
public let date: Date
public let dateFormatter: DateFormatter
Expand Down
2 changes: 1 addition & 1 deletion FormFramework.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "FormFramework"
s.version = "1.6.3"
s.version = "1.7.0"
s.module_name = "Form"
s.summary = "Powerful iOS layout and styling"
s.description = <<-DESC
Expand Down

0 comments on commit c31c4e2

Please sign in to comment.