Skip to content

Commit

Permalink
Merge pull request #119 from jaredegan/master
Browse files Browse the repository at this point in the history
Add ability to receive UITableViewDelegate & UIScrollViewDelegate messages from UITableView
  • Loading branch information
dmiluski authored Dec 11, 2017
2 parents aad79fa + b21c5fe commit d6861a5
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 3 deletions.
20 changes: 20 additions & 0 deletions Example/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class ViewController: TableViewController {
tableView.estimatedSectionHeaderHeight = 13.5
tableView.estimatedSectionFooterHeight = 13.5

dataSource = DataSource(tableViewDelegate: self)
dataSource.sections = [
Section(header: "Styles", rows: [
Row(text: "Value 1", detailText: "Detail", cellClass: Value1Cell.self),
Expand Down Expand Up @@ -89,6 +90,25 @@ class ViewController: TableViewController {
}
}

extension TableViewController: UITableViewDelegate {
// MARK: - UIScrollViewDelegate example functions
public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
// You can get UIScrollViewDelegate functions forwarded, even though the `DataSource` instance is the true delegate
// ...
}

// MARK: - UITableViewDelegate example functions
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
// You can get UITableViewDelegate functions forwarded, even though the `DataSource` instance is the true delegate
// ...
}

public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// The Row object's `selection` property will handle most of your use cases, but
// if you need to do something additional you can still implement this function.
}
}

class LargeAutoSizedExtremityView: UIView {
lazy var label: UILabel = {
let label = UILabel()
Expand Down
2 changes: 1 addition & 1 deletion Static.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = 'Static'
spec.version = '2.2.0'
spec.version = '2.3.0'
spec.summary = 'Simple static table views for iOS in Swift.'
spec.description = 'Static provides simple static table views for iOS in Swift.'
spec.homepage = 'https://github.com/venmo/static'
Expand Down
26 changes: 24 additions & 2 deletions Static/DataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,13 @@ public class DataSource: NSObject {

// MARK: - Initializers

/// Initialize with optional `tableView` and `sections`.
public init(tableView: UITableView? = nil, sections: [Section]? = nil) {
/// Initialize with optional `tableView`, `sections` and `tableViewDelegate`.
public init(tableView: UITableView? = nil, sections: [Section]? = nil, tableViewDelegate: UITableViewDelegate? = nil) {
assert(Thread.isMainThread, "You must access Static.DataSource from the main thread.")

self.tableView = tableView
self.sections = sections ?? []
self.tableViewDelegate = tableViewDelegate

super.init()

Expand All @@ -73,6 +74,23 @@ public class DataSource: NSObject {
return row(at: indexPath)
}

// MARK: - Forwarding UITableViewDelegate messages

/// If you have a use for `UITableViewDelegate` or `UIScrollViewDelegate` messages, you can use this property to receive those messages. `DataSource` needs to be the `UITableView` instance's true `delegate`, but will forward messages to this property.
/// You must pass this in the `init` function.
weak public private(set) var tableViewDelegate: UITableViewDelegate?

override public func forwardingTarget(for aSelector: Selector!) -> Any? {
if let forwardDelegate = tableViewDelegate, forwardDelegate.responds(to: aSelector) {
return forwardDelegate
} else {
return super.forwardingTarget(for: aSelector)
}
}

override public func responds(to aSelector: Selector!) -> Bool {
return super.responds(to: aSelector) || tableViewDelegate?.responds(to: aSelector) == true
}

// MARK: - Private

Expand Down Expand Up @@ -275,12 +293,16 @@ extension DataSource: UITableViewDelegate {
if let row = row(at: indexPath) {
row.selection?()
}

tableViewDelegate?.tableView?(tableView, didSelectRowAt: indexPath)
}

public func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
if let row = row(at: indexPath) {
row.accessory.selection?()
}

tableViewDelegate?.tableView?(tableView, accessoryButtonTappedForRowWith: indexPath)
}
}

Expand Down
27 changes: 27 additions & 0 deletions Static/Tests/DataSourceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,31 @@ class DataSourceTests: XCTestCase {
XCTAssertEqual(dataSource, tableView2.dataSource as? DataSource)
XCTAssertEqual(dataSource, tableView2.delegate as? DataSource)
}

func testTableViewDelegateForwarding() {
// Sample object that conforms to `UITableViewDelegate` protocol
class TestTableViewDelegate: NSObject, UITableViewDelegate {
static var delegateDidForward = false

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
TestTableViewDelegate.delegateDidForward = true
}
}

let sampleDelegate = TestTableViewDelegate()
let dataSource2 = DataSource(tableViewDelegate: sampleDelegate)

XCTAssertNotNil(dataSource2.tableViewDelegate)

let forwardingTarget = dataSource2.forwardingTarget(for: #selector(UITableViewDelegate.tableView(_:willDisplay:forRowAt:)))
XCTAssertNotNil(forwardingTarget)
XCTAssertNotNil(forwardingTarget as? TestTableViewDelegate)

// Test actual message
TestTableViewDelegate.delegateDidForward = false

(dataSource2 as UITableViewDelegate).tableView!(UITableView(), willDisplay: UITableViewCell(), forRowAt: IndexPath())
XCTAssertTrue(TestTableViewDelegate.delegateDidForward)

}
}

0 comments on commit d6861a5

Please sign in to comment.